MySQL Performance tuning
● Table_locks_immediate:产生表级锁定的次数;
● Table_locks_waited:出现表级锁定争用而发生等待的次数; 两个状态值都是从系统启动后开始记录,没出现一次对应的事件则数量加 1。如果这里的
Innodb 的行级锁定状态变量不仅记录了锁定等待次数,还记录了锁定总时长,每次平均时长,以及 最大时长,此外还有一个非累积状态量显示了当前正在等待锁定的等待数量。对各个状态量的说明如 下:
● Innodb_row_lock_time:从系统启动到现在锁定总时间长度;
此外,Innodb 出了提供这五个系统状态变量之外,还提供的其他更为丰富的即时状态信息供我们分 析使用。可以通过如下方法查看:
1. 通过创建 Innodb Monitor 表来打开 Innodb 的 monitor 功能:
mysql> create table innodb_monitor(a int) engine=innodb; Query OK, 0 rows affected (0.07 sec)
2. 然后通过使用“SHOW INNODB STATUS”查看细节信息(由于输出内容太多就不在此记录了);
“binlog_cache_size":在事务过程中容纳二进制日志 SQL 语句的缓存大小。二进制日志缓存是服 务器支持事务存储引擎并且服务器启用了二进制日志(—log-bin 选项)的前提下为每个客户端分配的内 存,注意,是每个Client都可以分配设置大小的binlog cache空间。如果读者朋友的系统中经常会出现 多语句事务的华,可以尝试增加该值的大小,以获得更有的性能。当然,我们可以通过 MySQL 的以下两 个状态变量来判断当前的 binlog_cache_size 的状况:Binlog_cache_use 和 Binlog_cache_disk_use。
“max_binlog_cache_size”:和"binlog_cache_size"相对应,但是所代表的是 binlog 能够使用的 最大 cache 内存大小。当我们执行多语句事务的时候,max_binlog_cache_size 如果不够大的话,系统可 能 会 报 出 “ Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage”的错误。
“max_binlog_size”:Binlog 日志最大值,一般来说设置为 512M 或者 1G,但不能超过 1G。该大小 并不能非常严格控制 Binlog 大小,尤其是当到达 Binlog 比较靠近尾部而又遇到一个较大事务的时候,系 统为了保证事务的完整性,不可能做切换日志的动作,只能将该事务的所有 SQL 都记录进入当前日志, 直到该事务结束。这一点和 Oracle 的 Redo 日志有点不一样,因为 Oracle 的 Redo 日志所记录的是数据文 件的物理位置的变化,而且里面同时记录了 Redo 和 Undo 相关的信息,所以同一个事务是否在一个日志中 对 Oracle 来说并不关键。而 MySQL 在 Binlog 中所记录的是数据库逻辑变化信息,MySQL 称之为 Event, 实际上就是带来数据库变化的 DML 之类的 Query 语句。
| 1048576 | | OFF | | 4294967295 | | 1073741824 | |0 |
“sync_binlog”:这个参数是对于 MySQL 系统来说是至关重要的,他不仅影响到 Binlog 对 MySQL 所 带来的性能损耗,而且还影响到 MySQL 中数据的完整性。对于“sync_binlog”参数的各种设置的说明如 下:
-
● sync_binlog=0,当事务提交之后,MySQL 不做 fsync 之类的磁盘同步指令刷新 binlog_cache 中 的信息到磁盘,而让 Filesystem 自行决定什么时候来做同步,或者 cache 满了之后才同步到磁 盘。
-
● sync_binlog=n,当每进行 n 次事务提交之后,MySQL 将进行一次 fsync 之类的磁盘同步指令来 将 binlog_cache 中的数据强制写入磁盘。
在 MySQL 中系统默认的设置是 sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性 能是最好的,但是风险也是最大的。因为一旦系统 Crash,在 binlog_cache 中的所有 binlog 信息都会被 丢失。而当设置为“1”的时候,是最安全但是性能损耗最大的设置。因为当设置为 1 的时候,即使系统 Crash,也最多丢失 binlog_cache 中未完成的一个事务,对实际数据没有任何实质性影响。从以往经验 和相关测试来看,对于高并发事务的系统来说,“sync_binlog”设置为 0 和设置为 1 的系统写入性能差 距可能高达 5 倍甚至更多。
大家都知道,MySQL 的复制(Replication),实际上就是通过将 Master 端的 Binlog 通过利用 IO 线 程通过网络复制到 Slave 端,然后再通过 SQL 线程解析 Binlog 中的日志再应用到数据库中来实现的。所 以,Binlog 量的大小对 IO 线程以及 Msater 和 Slave 端之间的网络都会产生直接的影响。
MySQL 中 Binlog 的产生量是没办法改变的,只要我们的 Query 改变了数据库中的数据,那么就必须 将该 Query 所对应的 Event 记录到 Binlog 中。那我们是不是就没有办法优化复制了呢?当然不是,在 MySQL 复制环境中,实际上是是有 8 个参数可以让我们控制需要复制或者需要忽略而不进行复制的 DB 或
者 Table ●
● ● ● ● ● ● ●
的,分别为:
Binlog_Do_DB:设定哪些数据库(Schema)需要记录 Binlog; Binlog_Ignore_DB:设定哪些数据库(Schema)不要记录 Binlog; Replicate_Do_DB:设定需要复制的数据库(Schema),多个 DB 用逗号(“,”)分隔; Replicate_Ignore_DB:设定可以忽略的数据库(Schema); Replicate_Do_Table:设定需要复制的 Table; Replicate_Ignore_Table:设定可以忽略的 Table;
Replicate_Wild_Do_Table:功能同 Replicate_Do_Table,但可以带通配符来进行设置; Replicate_Wild_Ignore_Table:功能同 Replicate_Ignore_Table,可带通配符设置;
通过上面这八个参数,我们就可以非常方便按照实际需求,控制从 Master 端到 Slave 端的 Binlog 量尽可能的少,从而减小 Master 端到 Slave 端的网络流量,减少 IO 线程的 IO 量,还能减少 SQL 线程的 解析与应用 SQL 的数量,最终达到改善 Slave 上的数据延时问题。
实际上,上面这八个参数中的前面两个是设置在 Master 端的,而后面六个参数则是设置在 Slave 端 的。虽然前面两个参数和后面六个参数在功能上并没有非常直接的关系,但是对于优化 MySQL 的 Replication 来说都可以启到相似的功能。当然也有一定的区别,其主要区别如下:
● 如果在 Master 端设置前面两个参数,不仅仅会让 Master 端的 Binlog 记录所带来的 IO 量减少, 还会让 Master 端的 IO 线程就可以减少 Binlog 的读取量,传递给 Slave 端的 IO 线程的 Binlog 量自然就会较少。这样做的好处是可以减少网络 IO,减少 Slave 端 IO 线程的 IO 量,减少 Slave 端的 SQL 线程的工作量,从而最大幅度的优化复制性能。当然,在 Master 端设置也存在一定的 弊端,因为 MySQL 的判断是否需要复制某个 Event 不是根据产生该 Event 的 Query 所更改的数据
所在的 DB,而是根据执行 Query 时刻所在的默认 Schema,也就是我们登录时候指定的 DB 或者运 行“USE DATABASE”中所指定的 DB。只有当前默认 DB 和配置中所设定的 DB 完全吻合的时候 IO 线程才会将该 Event 读取给 Slave 的 IO 线程。所以如果在系统中出现在默认 DB 和设定需要复制 的 DB 不一样的情况下改变了需要复制的 DB 中某个 Table 的数据的时候,该 Event 是不会被复制 到 Slave 中去的,这样就会造成 Slave 端的数据和 Master 的数据不一致的情况出现。同样,如 果在默认 Schema 下更改了不需要复制的 Schema 中的数据,则会被复制到 Slave 端,当 Slave 端 并没有该 Schema 的时候,则会造成复制出错而停止;
-
● “have_query_cache”:该 MySQL 是否支持 Query Cache;
-
● “query_cache_limit”:Query Cache 存放的单条 Query 最大 Result Set ,默认 1M;
-
● “query_cache_min_res_unit”:Query Cache 每个 Result Set 存放的最小内存大小,默认
4k;
-
● “query_cache_size”:系统中用于 Query Cache 内存的大小;
-
● “query_cache_type”:系统是否打开了 Query Cache 功能;
-
● “query_cache_wlock_invalidate”:针对于 MyISAM 存储引擎,设置当有 WRITE LOCK 在某个
Table 上面的时候,读请求是要等待 WRITE LOCK 释放资源之后再查询还是允许直接从 Query Cache 中读取结果,默认为 FALSE(可以直接从 Query Cache 中取得结果)。
以上参数的设置主要是“query_cache_limit”和“query_cache_min_res_unit”两个参数的设置需 要做一些针对于应用的相关调整。如果我们需要 Cache 的 Result Set 一般都很小(小于 4k)的话,可 以 适 当 将 “ query_cache_min_res_unit ” 参 数 再 调 小 一 些 , 避 免 造 成 内 存 的 浪 费 , “query_cache_limit”参数则不用调整。而如果我们需要Cache的 Result Set 大部分都大于4k的话, 则最好将“query_cache_min_res_unit”调整到和 Result Set 大小差不多,“query_cache_limit”的 参数也应大于 Result Set 的大小。当然,可能有些时候我们比较难准确的估算 Result Set 的大小, 那么当 Result Set 较大的时候,我们也并不是非得将“query_cache_min_res_unit”设置的和每个 Result Set 差不多大,是每个结果集的一半或者四分之一大小都可以,要想非常完美的完全不浪费任何 内存确实也是不可能做到的。
如果我们要了解Query Cache的使用情况,则可以通过Query Cache相关的状态变量来获取,如通过 如下命令:
-
● “Qcache_free_blocks”:Query Cache 中目前还有多少剩余的 blocks。如果该值显示较大, 则说明 Query Cache 中的内存碎片较多了,可能需要寻找合适的机会进行整理()。
-
● “Qcache_free_memory”:Query Cache 中目前剩余的内存大小。通过这个参数我们可以较为准 确的观察出当前系统中的 Query Cache 内存大小是否足够,是需要增加还是过多了;
-
● “Qcache_hits”:多少次命中。通过这个参数我们可以查看到 Query Cache 的基本效果;
-
● “Qcache_inserts”:多少次未命中然后插入。通过“Qcache_hits”和“Qcache_inserts”两
个参数我们就可以算出 Query Cache 的命中率了:
Query Cache 命中率 = Qcache_hits / ( Qcache_hits + Qcache_inserts );
-
● “Qcache_lowmem_prunes”:多少条 Query 因为内存不足而被清除出 Query Cache。通过 “Qcache_lowmem_prunes”和“Qcache_free_memory”相互结合,能够更清楚的了解到我们系
统中Query Cache的内存大小是否真的足够,是否非常频繁的出现因为内存不足而有Query被换
出
-
● “Qcache_not_cached”:因为 query_cache_type 的设置或者不能被 cache 的 Query 的数量;
-
● “Qcache_queries_in_cache”:当前 Query Cache 中 cache 的 Query 数量;
-
● “Qcache_total_blocks”:当前 Query Cache 中的 block 数量;
Query Cache 的限制
Query Cache 由于存放的都是逻辑结构的 Result Set,而不是物理的数据页,所以在性能提升的同时,也会受到一些特定的限制。
-
a) 5.1.17 之前的版本不能 Cache 帮定变量的 Query,但是从 5.1.17 版本开始,Query Cache 已经
开始支持帮定变量的 Query 了;
-
b) 所有子查询中的外部查询 SQL 不能被 Cache;
-
c) 在 Procedure,Function 以及 Trigger 中的 Query 不能被 Cache;
- d) 包 其他很多每次执行可能得到不一样结果的函数的 Query 不能被 Cache。