mysql memory=off_MySQL内存调优

原文链接: MySQL Memory Allocation -- by Rick James

原文日期: Created 2010; Refreshed Oct, 2012, Jan, 2014

翻译人员: 铁锚

翻译日期: 2014年5月28日

MySQL 内存分配—— 高速设置方案

假设仅使用MyISAM存储引擎,设置 key_buffer_size为可用内存的20%,(再加上设置 innodb_buffer_pool_size = 0 )

假设仅使用InnoDB存储引擎,设置 innodb_buffer_pool_size为可用内存的 70%, (设置 key_buffer_size = 10M,非常小但不是0.)

调优mysql的实践经验:

首先拷贝 my.cnf / my.ini 文件副本.

依据使用的存储引擎及可用内存,设置 key_buffer_size 和innodb_buffer_pool_size.

慢查询(Slow queries)的修正通常是通过加入索引(indexes),改变表结构(schema),改变 SELECT 语句 来实现,而不是通过数据库调优.

不要随便设置查询缓存(Query cache),除非你真正掌握它的优缺点以及适用场景.

不要改变其它的參数,除非你遇到了相应的问题(如最大连接数问题, max connections).

确保改动的是 [mysqld] 这一节下的内容,而不是其它部分.以下向您展示一些实际的细节. (本文不涉及 NDB Cluster)

什么是索引缓存(key_buffer)?

MyISAM引擎的缓存分为两部分.

索引块(Index blocks,每一个1 KB,BTree结构、存放于 .MYI 文件) 缓存到 “key buffer” 中.

数据块缓存(Data block caching, 存放于 .MYD 文件里)交给操作系统负责, 所以确保留下了适量的空暇内存(给操作系统).警告: 某些类型的操作系统总是报告说内存使用超过90%,尽管实际上还有非常多的空暇内存.

SHOW GLOBAL STATUS LIKE 'Key%'; 运行后计算 Key_read_requests / Key_reads 的值, 假设比值较大(比方大于10), 那么 key_buffer 就足够了.

什么是缓存池(buffer_pool)?

InnoDB将全部缓存都放在 “buffer pool” 中, 缓存池的大小通过 innodb_buffer_pool_size控制. 包括被打开表(open tables)中的 16KB一块的数据/索引块,此外还有一些附加开销.

MySQL 5.5(以及带插件的 5.1版本号)同意您指定 块大小(block size)为 8 KB或4 KB. MySQL 5.5能够有多个缓冲池,由于每一个缓存池有一个相互排斥锁, 所以设置多个池能够缓解一些相互排斥锁瓶颈.

SHOW TABLE STATUS; 显示各个数据库中全部表的状态.计算全部MyISAM表的 Index_length 值的总和. 让 key_buffer_size 小于等于这个和值.

计算全部 InnoDB表 Data_length + Index_length 值的总和. 设置 innodb_buffer_pool_size 为不超过总和值的110%.假设有内存交换(swapping发生),须要将两个參数适量地按减小一些.

运行以下的SQL语句查看适合的參数值. (假设有非常多表,可能耗时几分钟.)

SELECT ENGINE,

ROUND(SUM(data_length) /1024/1024, 1) AS "Data MB",

ROUND(SUM(index_length)/1024/1024, 1) AS "Index MB",

ROUND(SUM(data_length + index_length)/1024/1024, 1) AS "Total MB",

COUNT(*) "Num Tables"

FROM INFORMATION_SCHEMA.TABLES

WHERE table_schema not in ("information_schema", "performance_schema")

GROUP BY ENGINE;相互排斥锁瓶颈

MySQL 是单核CPU时代设计的,且能够非常easy移植到不同的硬件体系架构中. 不幸的是,这导致了对连结锁(interlock)操作的凌乱. 在几个重要的流程中存在少量(非常少)的“相互排斥(mutexes)”. 包括:

MyISAM的 key_buffer

查询缓存(Query Cache)

InnoDB的buffer_pool随着多核CPU的盛行,相互排斥问题引起了MySQL的性能问题. 一般来说,CPU超过 4~8 核越多,则MySQL变得越慢,而不会更快. MySQL 5.5 中 InnoDB 的增强版 Percona XtraDB 对多核CPU的支持要好非常多; 实际的限制大致是32核, CPU核心超过这个数后性能会达到瓶颈 ,但不再下降. MySQL 5.6版声称最多能够支持48核.

超线程和多核CPU

简单的处理方式:

禁用超线程(HyperThreading)

停用超过8个核心以上的部分

超线程这里主要是指曾经的超线程技术,因此此部分可能不一定正确.超线程适合拿来做营销宣传,但对(专用应用的)性能极不友好. 有两个处理单元在共享同一个物理缓存. 假设这两个线程在做相同的事情,缓存会相当高效. 假设这俩线程在干不同的事,他们会相互妨碍到还有一个(超)线程的缓存项.

总的来说MySQL在多核处理上并不占优势. 所以,假设禁用超线程(HT),剩下的核心将会运行得更快一点.

32位操作系统和MySQL

(译者注: 肯定64位的MySQL在 32位OS上跑不起来...)

首先,操作系统(以及硬件?) 会限制进程不能使用4GB RAM中的全部,假设有 4G内存的话. 假设物理 RAM 超过 4 GB, 超过的部分在32位操作系统中不可訪问,也是不可用的.

其次,操作系统可能会限制单个进程最大使用多少内存.

比如:FreeBSD的 maxdsiz ,默觉得512 MB.

演示样例:

$ ulimit -a

...

max memory size (kbytes, -m) 524288因此,确定了 mysqld有多少可用内存, 就能够设置为 20% ~ 70%,但须要适当的减少一些.

假设系统报错,比如[ERROR] /usr/libexec/mysqld: Out of memory (Needed xxx bytes) , 可能是MySQL申请了超过操作系统同意的内存范围. 须要减小缓存设置.

64位OS与32位MySQL

64位操作系统不受4 GB内存的限制,但32位MySQL依旧受这个限制.

假设你有 4 GB以上的内存,那么能够设置:

key_buffer_size = 20%(全部RAM的),但不要超过3 GB.

buffer_pool = 3G当然最好的办法是将MySQL换成64位版本号.

64位OS与64位MySQL

仅仅使用MyISAM引擎: (5.0.52 ~ 5.1.23之前的)key_buffer_size有 4GB的硬性限制. 详情请參考MySQL 5.1 限制(restrictions)在更高版本号中,设置 key_buffer_size 为 20%的RAM. 在(my.cnf / my.ini)中加上 innodb_buffer_pool_size = 0.

仅仅使用InnoDB引擎: 设置 innodb_buffer_pool_size = 70%的RAM. 假设内存非常大,并使用 5.5(及以上)版本号,能够考虑使用 多个缓存池. 推荐设置 1 - 16 个  innodb_buffer_pool_instances, 每一个都不小于1 GB. (非常抱歉,没有最优设置为多少个的具体參考指标;但应该不能设置太多).与此同一时候,设置 key_buffer_size = 20M(非常小,但不是零)

假设你在数据库中混合使用多个引擎,将两个值都减少一些.

最大连接数,线程栈

(max_connections,thread_stack)

每一个“线程”都要占用一定的内存. 通常为 200 KB左右; 因此 100个线程大概就是 20 MB. 假设设置 max_connections= 1000,那大概就须要 200 MB,或者很多其它. 同一时候连接数太大可能会引起其它某些问题,这点须要注意.

在5.6(或 MariaDB5.5)中,能够选择线程池与 max_connections 交互. 这是一个高级话题.

线程栈溢出非常少出现. 假设确实发生了,能够设置: thread_stack = 256K

很多其它关于ulimit的讨论请点击这里

(这一段是有争议的.) 还有一方面,表缓存(过去?)的实现方式非常低效 —— 查找通过线性扫描来完毕. 因此,设置 table_cache 为几千确实会使得 mysql变慢. (基准測试也证明了这一点.)

你能够通过 SHOW GLOBAL STATUS; 查看系统的性能信息, 并计算 每秒打开数(opens/second): Opened_files /Uptime , 假设这个值较大,比如大于 5, 那么应该加大 table_cache; 假设非常小,比方是 1,通过减小 table_cache 值,可能会对性能有所改善.

查询缓存(Query Cache)

简短的回答: 设置 query_cache_type = OFF 及 query_cache_size = 0

QC(Query Cache)实际上是将 SELECT语句与结果集(resultsets)进行散列映射.

具体的回答…… 关于“查询缓存”有很多种观点; 当中很多是负面的.

新手警告! QC与key_buffer和buffer_pool全然无关.

当命中时, QC速度快如闪电. 要创建一个运行快1000倍的基准測试并不难.

在QC中仅仅有一个相互排斥锁(译者注: 锁越少,就是锁钥匙越少,高并发时就会激烈竞争/等待).

除非将QC设置为OFF与0,否则每次查询都会去对照一遍.

真相,相互排斥锁会发生碰撞,即使 query_cache_type = DEMAND (2).

真相,相互排斥锁会发生碰撞,即便设置了 SQL_NO_CACHE.

查询语句仅仅要变了一点点(即使多了个空格)都可能导致在QC中生成多个不同的缓存项.“改动”是代价高昂与频繁的:

在一个表中发生不论什么 write 事件, QC中相应到这个表的全部条目都会被清除.

即便在仅仅读从server(readonly Slave)上也是这样.

清除使用的是线性算法来运行,所以QC较大(比方200MB)则会导致速度明显地变慢.要查看QC的运行效率怎样,运行 SHOW GLOBAL STATUS LIKE 'Qc%'; 然后计算read的命中率: Qcache_hits / Qcache_inserts, 假设大于5,则 QC的效率还不错.

假设QC适合你的应用,那么我推荐:

query_cache_size = 不超过50M

query_cache_type = DEMAND

在全部 SELECT 语句中指明 SQL_CACHE 或 SQL_NO_CACHE, 依据哪些查询可能会从QC缓存中命中.深入了解Query Cache

thread_cache_size

这是一个非常小的调优项. 设置为 0 会减少线程(连接)创建的速度. 设置为较小的值(比方 10) 是比較好的. 该选项对RAM没有多少影响.

它是server额外保持的线程数量,不会影响实际线程数; 起限制作用的是 max_connections.

二进制日志

假设为 复制(replication) 或 时间点恢复(point-in-time recovery) 启用二进制日志(通过 og_bin开启), 则server将一直记录二进制日志(binary logs). 也就是说,可能慢慢地占用磁盘. 建议设置expire_logs_days = 14 ,仅仅保留14天的日志记录.

swappiness

RHEL,非常英明地,同意用户自己控制 OS 怎样进行预先内存交换分配. 总的来说这是非常好的策略,但对MySQL来说则是一个灾难.

(感觉翻译的有点不流畅,本段原文为: RHEL, in its infinite wisdom, decided to let you control how aggressively the OS will preemptively swap RAM. This is good in general, but lousy for MySQL)MySQL期望相当稳定的内存分配 —— 缓存(大部分)是预先分配的; 线程(大都)是限制数量的. 不论什么内存交换都可能极大地损害MySQL的性能.

设置非常高的swappiness值,会丢失一些内存,由于操作系统试图为以后的分配保留大量的自由空间(MySQL通常是不须要的).

设置swappiness = 0,不交换,在内存不足时操作系统可能会崩溃,. 我宁愿MySQL一卡一卡的,也不希望他崩了.

对于MySQL-only(专用)server, 中间数(比方5 ?)可能是一个非常好的值.

NUMA

OK,是时候了解一些CPU管理内存的架构了. 我们先看 NUMA(Non-Uniform Memory Access, 非统一内存寻址). 每一个CPU(或多路server中的每一个socket(CPU插座)) 都挂载有一部分内存. 这使得訪问本地(local) RAM 非常快, 而訪问挂载在其它 CPU下的RAM要慢上数十个周期.

接着看操作系统. 在(RHEL ?

)非常多情形下,有两个行为:OS分配的内存固定到 “first(第一个)” CPU名下.

接着分配的其它内存也默认分配到第一个CPU名下,直到它满了.如今问题来了.

OS与MySQL分配完了第一个 CPU的全部RAM.

MySQL分配了第二个 CPU的部分内存.

操作系统OS还须要分配一些其它内存.Ouch —— 一个CPU须要分配内存,但自己名下控制的RAM已经耗尽了,所以它将MySQL的部分内存置换出去. 渣渣!

可能的解决方式:配置BIOS内存分配为 “interleave”(交错). 这将防止过早交换(premature swapping),代价是有一半左右的 RAM 訪问要跨CPU(off-CPU). 嗯,不论怎样訪问的代价都较大, 假设真的要使用全部内存的话.

总体性能损失/收益:几个百分点.

大内存分页(huge pages)

这里有还有一个硬件性能陷阱.

CPU訪问RAM,特别是将64位地址映射到某个地方, 比方 128 GB 或“真实”的RAM,会使用TLB. (TLB =Translation Lookaside Buffer,旁路转换缓冲.) TLB是硬件实现的内存关联查找表; 将64位的虚拟地址转换到实际的物理地址.

由于TLB是一个小的,虚拟寻址的缓存,有时会发生 “misses”(未命中),那就会进入物理RAM来查找. 这是两次查找是非常费时的操作,所以应该避免.

通常,内存被 “分页” 为 4 KB一页,TLB实际上将高位的(64 - 12)位映射到一个特定页面. 而低12位通过虚地址转换得到完整的地址.

比如,128 GB的RAM按 4 KB分页须要 32M(3200万个) page-table条目. 这太大了, 远远超过TLB的容量. 所以陷入了“Huge page”的骗局.

随着硬件与操作系统的支持,使部分RAM成为巨型页面成为可能 ,比方说4 MB(而不是4 KB). 这使得TLB条目剧减,对这部分RAM来说分页单元是4 MB. 因此,巨大的页面相当于是不分页的(non-pagable).

如今内存被分为 pagable 和 non pagable 两部分; 哪些部分 non pagable 是合理的?

在MySQL中, innodb_buffer_pool 就是一个完美的使用者. 通过正确地配置这些,InnoDB能跑得更快一点:启用 Huge pages

通知操作系统分配适当的数量(和 buffer_pool 个数一致)

通知MySQL使用huge pagesMEMORY引擎(ENGINE=MEMORY)

这是一个不经常使用的存储引擎,算是MyISAM和InnoDB的替代品. 其数据不是持久的,所以其应用范围相当有限. 内存表的大小受限于 max_heap_table_size ,默认值是16 MB. 我提起它,以防你将此值改动得太大;这会偷偷地占用可用的RAM.

怎样设置变量(VARIABLEs)

在文本文件my.cnf中(Windows上是my.ini),加入一行,比如

innodb_buffer_pool_size = 5G

即: 变量名,等号“=”,变量的值. 有些值同意缩写,如M代表 million(1048576),G代表billion.

要让server看到这些设置,必须将其放到配置文件的 “[mysqld]”节下.

对 my.cnf 或 my.ini的设置不会马上生效,须要你重新启动server.

大多数的设置能够通过 root 账号登陆后在线改动  (其它 SUPER权限账号也能够),比如:

SET @@global.key_buffer_size = 77000000;

注意:此处不同意设置 M 或 G 等单位.

查看全局变量的设置信息:

mysql> SHOW GLOBAL VARIABLES LIKE "key_buffer_size";

+-----------------+----------+

| Variable_name | Value |

+-----------------+----------+

| key_buffer_size | 76996608 |

+-----------------+----------+注意,这部分设置MySQL会向下取整,对齐到一定的数字.

你可能须要改动两个地方(运行SET 并改动my.cnf),以使改动马上生效,而且下次重新启动后依旧是相同的值(无论是手动,还是其它原因又一次启动)

Webserver

像Apache这种webserver使用多线程来处理. 假设每一个线程打开一个 MySQL连接,可能会超过同意的最大连接数. 确保将webserver的 MaxClients (或相似參数) 设置为一个合理的值(如50以下).

工具

MySQLTuner

TUNING-PRIMER上面是几个对内存设置建议的工具. 当中有一个误导性条目:

Maximum possible memory usage: 31.3G(266% of installed RAM)

可能使用的内存最大值为: 31.3G (可能是物理内存的 266%)

不要让它吓到你,这些工具使用的公式过于保守了. 他们假设全部 max_connections 都在使用而且处于活跃状态,并正在运行一些内存密集型的工作.

Total fragmented tables: 23

有碎片的tables: 23 个

这意味着 OPTIMIZE TABLE 可能会有作用. 我建议对表设置高百分比的 “free space”(见SHOW TABLE STATUS) 或者你知道对什么表做了大量的删除/更新操作. 只是,不必费心频繁地对table进行OPTIMIZE 优化整理. 一个月一次可能就够了.

文章改动记录

2010创建;2012年10月更新,2014年1月更新;

更深入的文章:

MySQL 5.6的调优

InnoDB性能优化的基本知识(终极版)

MySQL安装后的10项优化设置

通过 MySQL论坛::性能 联系作者 ——里克·詹姆斯

里克·詹姆斯的MySQL相关文档

提示,调试、howto、优化相关等等……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Seajs的用法

以前经常听到Seajs,但是没深入了解过,不清楚到底是用做哪个方面,后来调组到M站做开发,发现项目用到了Seajs,便去了解下 SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及…

java 调用私有方法_公开调用私有Java方法?

java 调用私有方法我们是Java开发人员,在Java中已知4种访问修饰符:私有,受保护,公共和包。 好吧,除了私有以外,最后三个可以通过继承,相同的包或实例从类外部调用。 现在,常见的问题…

mysql慢查询开启语句分析_linux下开启mysql慢查询,分析查询语句

mysql> show variables like "%long%"; //查看一下默认为慢查询的时间10秒----------------------------| Variable_name | Value |----------------------------| long_query_time | 10.000000 |----------------------------1 row in set (0.00 sec)mysql> s…

港航环境变化引起的错误解决方法

1.serlvet API缺少,pom.xml中引入坐标; 2.web.xml中出现错误,将所有的filter调到filtermapping上面去; 3.依赖导入完成后项目依然有红叉,右击项目Propreties->myeclipse->Project Facets->java换成1.6就可以了…

flutter 国际化_从0开始设计Flutter独立APP | 第二篇: 完整的国际化语言支持

鉴于Flutter高性能渲染和跨平台的优势,闪点清单在移动端APP上,使用了完整的Flutter框架来开发。既然是完整APP,架构搭建完全不受历史Native APP的影响,没有历史包袱的沉淀,设计也能更灵活和健壮。国际化语言的支持&…

将旧版本从Java EE 5减少到7

Java EE 5于2005年首次引入,而Java EE 7于2013年问世。这两个版本之间有7年的差距,从技术角度来说,这就像一个世纪。 许多组织仍然对使用Java EE 5感到困惑,并且有很多正当理由选择不升级。 不过,如果您考虑一些前进的…

struts2知识

一、 MVC Model 1:将所有的程序代码,都写到JSP页面中。 Model 2:JSP(流程控制、数据显示) JavaBean 改进的Model2:Servlet(流程控制) Jsp(数据显示) Ja…

mysql 数据修改时间_怎样修改mysql数据中的具体时间

匿名用户1级2016-12-30 回答应用场景:1、在数据表中,要记录每条数据是什么时候创建的,不需要应用程序去特意记录,而由数据数据库获取当前时间自动记录创建时间;2、在数据库中,要记录每条数据是什么时候修改…

sql插入临时表数据的方法

方法有两种,主要看需求。 方法1:定义好临时表的字段和类型、插入对应的值 create table #Tmp --创建临时表#Tmp (City varchar(50), --Country varchar(50), -- );insert #Tmp select 北京,中国 union select 东京,日本 union select 纽约,美国 se…

mysql冷热备_Mysql的冷备热备(数据备份)

冷备可以是mysql工具 msqldump。mysqldump -u username -p dbname table1 table2 ... -> BackupName.sqldbname 数据库名称table1 table2 是表名称BackupName.sql 备份保存的相对路径的sql文件执行下面命令。mysqldump -u homestead -psecret homestead > /home/vagrant/…

拼图项目:一个不完整的难题

马克雷因霍尔德(Mark Reinhold)最近提议延迟Java 9,以花更多的时间来完成Jigsaw项目,这是即将发布的版本的主要功能。 虽然这个决定肯定会使Java的厄运论者重回舞台,但我个人感到很放心,并认为这是一个很好…

gulp

1.gulp是什么? gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;使用她,不仅可以很愉快的编…

往vxe-table添加渲染器怎么添_赚大了!飘窗上装书桌,加扇折叠窗,等于为家里又多添一间房...

阅读本文前,请您先点击上面蓝色字体,再点关 注这样您就可以继续免费收到文章注:本文转载自网络,如有侵权,请在后台留言联系我们进行删除,谢谢! …

Kubernetes资源创建yml语法

前言 在是用kubernetes中,我们对资源的创建大部分都是通过 1kubelet create -f RESOURCE.yaml刚开看的时候不免有一些迷茫,看不懂语法,不知道怎么写;今天本文就介绍一下kubernetes construct语法。 Construct语法其实就是由kubele…

【六大排序详解】中篇 :选择排序 与 堆排序

选择排序 与 堆排序 选择排序 选择排序 与 堆排序1 选择排序1.1 选择排序原理1.2 排序步骤1.3 代码实现 2 堆排序2.1 堆排序原理2.1.1 大堆与小堆2.1.2 向上调整算法2.1.3 向下调整算法 2.2 排序步骤2.3 代码实现 3 时间复杂度分析 Thanks♪(・ω・)&#…

java中contains的用法_java容器中所有接口和类的用法

我这里讲一下如何下载java的api文档还有就是容器和容器之间进行的操作每一个地方称之为一个节点,每一个节点包含了3部分(上一个节点,下一个节点,以及我们自己的数据部分)需要多个线程共享的时候通过键对象来找值对象1 java中的length属性是针…

lcs文本相似度_具有LCS方法的通用文本比较工具

lcs文本相似度常见的问题是检测并显示两个文本的差异(尤其是几百行或几千行)。 使用纯java.lang.String类方法可能是一种解决方案,但是对于此类操作最重要的问题是,“性能”将不能令人满意。 我们需要一种有效的解决方案&#xff…

MySQL--开发技巧(一)

Inner Join: Left Outer Join: Right Outer Join: Full Join: Cross Join: SELECT t1.attrs ,t2.attrs FROM t1 CROSS JOIN t2 使用Join更新表: UPDATE table1 SET attr2 WHERE attr1 IN (SELECT table2.attr1 FROM table1 INNER JOIN table2 ON tab…

查看mysql 中建立的表空间_mysql 表空间及索引的查看

1.查看索引(1)单位是GBSELECT CONCAT(ROUND(SUM(index_length)/(1024*1024*1024), 2), GB) AS Total Index Size FROM information_schema.TABLES WHERE table_schema LIKE database;------------------| Total Index Size |------------------| 1.70 GB |------------------(…

Java EE,Gradle和集成测试

在过去的几年中,Apache Maven已成为Java和Java EE项目的事实上的构建工具。 但是从两年前开始, Gradle便获得了越来越多的用户。 在我之前的文章( http://www.lordofthejars.com/2015/10/gradle-and-java-ee.html )之后&#xff0…