MySQL 是目前企业最常见的数据库之一,占用绝大部分市场份额。在日常维护管理的 过程中相信大家肯定会遇到很多常见的故障。为了提高故障处理的及时性,本章案例将常见 故障进行汇总,增长学习经验。生产环境中数据库的默认配置无法满足高性能网站架构的需 求,本章会从实际工作经验出发,总结 MySQL 数据库应该如何优化。
要学习如何优化,首先要对 MySQL 的逻辑架构深入的了解。下图是 MySQL 逻辑架 构图,可以让我们更清晰了解 MySQL 的运行原理。
最上层是一些客户端和连接服务,包含本地 sock 通信和大多数基于客户端/ 服务器端工具实现的 TCP/IP 通信。主要完成一些连接处理、授权认证、及相关的安全方案 等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上 可以实现基于 SSL 的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作 权限。
第二层架构主要完成大多数的核心服务功能,如 SQL 接口、缓存的查询、SQL 的分析 和优化以及部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如过程、函数等。 在该层上服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化,如确定查询 表的顺序,是否利用索引等,最后生成相应的执行操作。如果是 select 语句,服务器还会 查询内部的缓存。如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系 统的性能。
存储引擎层,存储引擎真正的负责了 MySQL 中数据的存储和提取,服务器通过 API 与存储引擎进行通信。不同的存储引擎具有的功能不同,可以根据自己的实际需要进行选取。
数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的 交互。
本案例故障汇总和优化相当于是对数据库经验的总结。案例环境比较简单,只需一台数 据库模拟单实例环境,另外两台数据库模拟主从环境本次MySQL 版本使用的是 5.7
(1)MySQL 常见故障解决。
(2)MySQL 性能优化。
(1)单库常见故障分析。
(2)主从常见故障分析。
(3)从几个不同方面优化 MySQL。
(1) 故障现象 1
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/data/mysql/mysql.sock' (2)
问题分析:
以上这种情况一般都是数据库未启动或者数据库端口被防火墙拦截导致。
解决方法:
启动数据库或者防火墙开放数据库监听端口。
(2)故障现象 2
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
问题分析:
密码不正确或者没有权限访问。
解决方法:
1 修改 my.cnf 主配置文件,在[mysqld]下添加 skip-grant-tables,重启数据库。最后 修改密码命令如下。
mysql>use mysql;
mysql> update mysql.user set authentication_string=password('123456') where user='root' and Host = 'localhost';
mysql> flush privileges;
再删除刚刚添加的 skip-grant-tables 参数,重启数据库,使用新密码即可登录。
2 重新授权,命令如下。
mysql>grant all on *.* to 'root'@'mysql-server' identified by '123456';
(3)故障现象 3
在使用远程连接数据库时偶尔会发生远程连接数据库很慢的问题。
问题分析:
如果 MySQL 主机查询 DNS 很慢或是有很多客户端主机时会导致连接很慢. 由于开发机器是不能够连接外网的,在进行 MySQL 连接时,DNS 解析是不可能完成的, 从而也就明白了为什么连接那么慢了。
解决方法:
修改 my.cnf 主配置文件,在[mysqld]下添加 skip-name-resolve,重启数据 库可以解决。注意在以后授权里面不能再使用主机名授权。
(4)故障现象 4
Can't open file: 'xxx_forums.MYI'. (errno: 145)
问题分析:
●服务器非正常关机,数据库所在空间已满,或一些其它未知的原因,对数据库表造 成了损坏。
●可能是操作系统下直接将数据库文件拷贝移动,会因为文件的属组问题而产生这个 错误。
解决方法:
● 可以使用下面的两种方式修复数据表(第一种方法仅适合独立主机用户):
◆ 使用 MySQL 自带的专门用户数据表检查和修复工具 myisamchk。一般 情况下只有在命令行下面才能运行 myisamchk 命令。常用的修复命令为:
myisamchk -r 数据文件目录/数据表名.MYI;
◆ 通过 phpMyAdmin 修复, phpMyAdmin 带有修复数据表的功能,进入 到某一个表中后,点击“操作”,在下方的“表维护”中点击“修复表”即可。
**注意:**以上两种修复方式在执行前一定要备份数据库
● 修改文件的属组(仅适合独立主机用户):
◆ 复制数据库文件的过程中没有将数据库文件设置为 MySQL 运行的帐号 可读写(一般适用于 Linux 和 FreeBSD 用户)。
(5)故障现象 5
ERROR 1129 (HY000): Host 'xxx.xxx.xxx.xxx' is blocked because of many connection errors;
unblock with 'mysqladmin flush-hosts
问题分析:
由于 mysql 数据库的参数:max_connect_errors,其默认值是 10。当大量 (max_connect_errors)的主机去连接 MySQL,总连接请求超过了 10 次,新的连接就再也无 法连接上 MySQL 服务。同一 个 ip 在短时间内产生太多中断的数据库连接而导致的阻塞(超过 mysql 数据库 max_connection_errors 的最大值)。
解决方法:
● 使用 mysqladmin flush-hosts 命令清除缓存,命令执行方法如下:
mysqladmin -uroot -p -h 192.168.241.48 flush-hosts
Enter password:
●修改 mysql 配置文件,在[mysqld]下面添加 max_connect_errors=1000,然后重 启 MySQL。
(6)故障现象 6
客户端报 Too many connections。
问题分析:
连接数超出 Mysql 的最大连接数限制。
解决方法:
● 在 my.cnf 配置文件里面增大连接数,然后重启 MySQL 服务。
max_connections = 10000
● 临时修改最大连接数,重启后不生效。需要在 my.cnf 里面修改配置文件,下次重启生效。
set GLOBAL max_connections=10000;
(7)故障现象 7
Warning: World-writable config file '/etc/my.cnf' is ignored ERROR! MySQL is running but PID file could not be found
问题分析:
MySQL 的配置文件/etc/my.cnf 权限不对。
解决方法:
chmod 644 /et/my.cnf
(8)故障现象 8
InnoDB: Error: page 14178 log sequence number 29455369832
InnoDB: is in the future! Current system log sequence number 29455369832
问题分析:
innodb 数据文件损坏。
解决方法:
修改 my.cnf 配置文件,在[mysqld]下添加 innodb_force_recovery=4, 启动 数据库后备份数据文件,然后去掉该参数,利用备份文件恢复数据。
(1)故障现象 1
从库的 Slave_IO_Running 为 NO
The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).
问题分析:
主库和从库的 server-id 值一样。
解决方法:
修改从库的 server-id 的值,修改为和主库不一样。修改完后重启,再同步 即可。
(2)故障现象 2
从库的 Slave_IO_Running 为 NO
问题分析:造成从库线程为 NO 的原因会有很多,主要原因是主键冲突或者主库删除或 更新数据,从库找不到记录,数据被修改导致。通常状态码报错有 1007、1032、1062、1452 等。
解决方法一:
mysql> stop slave;
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave;
解决方法二:
设置用户权限,设置从库只读权限
set global read_only=true;
(3)故障现象 3
Error initializing relay log position: I/O error reading the header from the binary log
分析问题:
从库的中继日志 relay-bin 损坏。
解决方法:
手工修复,重新找到同步的 binlog 和 pos 点,然后重新同步即可。
mysql>CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.xxx',MASTER_LOG_POS=xxx;
1. 硬件方面
说到服务器硬件,最主要的无非 CPU、内存、磁盘三大关键因素。
(1)关于 CPU CPU 对于 MySQL 应用,推荐使用 S.M.P.架构的多路对称 CPU。例如:可以使用两颗 Intel Xeon 3.6GHz 的 CPU。现在比较推荐用 4U 的服务器来专门做数据库服务器,不仅仅 是针对于 MySQL。
(2)关于内存 物理内存对于一台使用 MySQL 的 Database Server 来说,服务器内存建议不要小于 2GB,推荐使用 4GB 以上的物理内存。不过内存对于现在的服务器而言可以说是一个可以 忽略的问题,工作中遇到了高端服务器基本上内存都超过了 32G。
(3)关于磁盘 磁盘寻道能力(磁盘 I/O)。以目前市场上普遍高转速 SAS 硬盘(15000 转/秒)为例, 这种硬盘理论上每秒寻道 15000 次,这是物理特性决定的,没有办法改变。 MySQL 每秒 钟都在进行大量、复杂的查询操作,对磁盘的读写量可想而知。所以通常认为磁盘 I/O 是制 约 MySQL 性能的最大因素之一,通常是使用 RAID-0+1 磁盘阵列,注意不要尝试使用 RAID-5,MySQL 在 RAID-5 磁盘阵列上的效率并不高。如果不考虑硬件的投入成本,也可 以考虑固态(SSD)硬盘专门作为数据库服务器使用。数据库的读写性能肯定会提高很多。
2. MySQL 配置文件
通常默认的 my.cnf 配置文件无法发挥出 MySQL 最高的性能,所以需要根据不同的硬 件进行优化,配置文件的优化也是重点。下面是物理内存为 32G 的数据库优化参数,具体 从全局、二进制日志、主从、innodb、myisam 几个方面优化,仅供参考。
(1)default-time-zone=+8:00
默认 MySQL 使用的是系统时区,修改为北京时间,也就是所说的东八区。
(2)interactive_timeout = 120
服务器关闭交互式连接前等待活动的秒数。
(3)wait_timeout = 120
服务器关闭非交互连接之前等待活动的秒数。
(4)open_files_limit = 10240
MySQL 服务器打开文件句柄数限制。
(5)group_concat_max_len = 102400
MySQL 默认的拼接最大长度为 1024 个字节,由于 1024 个字节会出现不够用的情况, 根据实际情况进行修改。
(6)user=mysql
使用 mysql 用户运行。
(7)character-set-server=utf8、init_connect=‘SET NAMES utf8’
设置字符集为 utf8
(8)back_log = 600
在 MySQL 暂时停止响应新请求之前,短时间内的多少个请求可以被存在堆栈中。如果 系统在短时间内有很多连接,则需要增大该参数的值,该参数值指定到来的 TCP/IP 连接的 监听队列的大小。默认值 50。
(9)max_connections = 5000
MySQL 允许最大的进程连接数,如果经常出现 Too Many Connections 的错误提示, 则需要增大此值。
(10)max_connect_errors = 6000
设置每个主机的连接请求异常中断的最大次数。当超过该次数,MySQL 服务器将禁止 host 的连接请求,直到 MySQL 服务器重启或通过 flush hosts 命令清空此 host 的相关信息。
(11)table_cache = 1024
数据表调整缓冲区大小。它设置表高速缓存的数目。每个连接进来,都会至少打开一个 表缓存。因此,table_cache 的大小与 max_connections 的设置有关。例如,对于 200 个 并行运行的连接,应该让表的缓存至少有 200×N。这里 N 是应用可以执行查询的一个连接 中表的最大数量。
此外,还需要为临时表和文件保留一些额外的文件描述符。 当 MySQL 访问一个表时, 如果该表在缓存中已经被打开,则可以直接访问缓存。如果还没有被缓存,但是在 MySQL 表缓冲区中还有空间,那么这个表就被打开并放入表缓冲区。如果表缓存满了,则会按照一 定的规则将当前未用的表释放,或者临时扩大表缓存来存放,使用表缓存的好处是可以更快 速地访问表中的内容。执行 flushtables 会清空缓存的内容。
一般来说,可以通过 showstatus 命令查看数据库运行峰值时间的状态值 Open_tables 和 Opened_tables,判断是否需要增加 table_cache 的值(其中 open_tables 是当前打开的 表的数量,Opened_tables 则是已经打开的表的数量)。若 open_tables 接近 table_cache, 并且 Opened_tables 值在逐步增加,那就要考虑增加这个值的大小了。还有就是 Table_locks_waited 比较高的时候,也需要增加 table_cache。
(12)table_open_cache = 2048
指定表高速缓存的大小。每当 MySQL 访问一个表时,如果在表缓冲区中还有空间,该 表就被打开并放入其中,这样可以更快地访问表内容。
(13)max_heap_table_size = 256M
这个变量定义了用户可以创建的内存表(memory table)的大小。这个值用来计算内存表 的最大行数值。这个变量支持动态改变,即 set @max_heap_table_size=#。但是对于已经 存在的内存表就没有什么用了,除非这个表被重新创建(create table)、修改(alter table)或者 truncate table。服务重启也会设置已经存在的内存表为全局 max_heap_table_size 的值。
(14)external-locking = false
使用 skip-external-lockingMySQL 选项以避免外部锁定。该选项默认开启。
(15)max_allowed_packet = 32M
设置在网络传输中一次消息传输量的最大值。系统默认值为 1MB,最大值是 1GB,必 须设置 1024 的倍数。
(16)sort_buffer_size = 512M
Sort_Buffer_Size 是一个 connection 级参数,在每个 connection(session)第一次需 要使用这个 buffer 的时候,一次性分配设置的内存。Sort_Buffer_Size 并不是越大越好,由 于是 connection 级的参数,过大的设置+高并发可能会耗尽系统内存资源。
(17)join_buffer_size = 8M
用于表间关联缓存的大小,和 sort_buffer_size 一样,该参数对应的分配内存也是每个 连接独享。
(18)thread_cache_size = 300
服务器线程缓存这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果 缓存中还有空间,那么客户端的线程将被放到缓存中;如果线程重新被请求,那么请求将从 缓存中读取;如果缓存中是空的或者是新的请求,那么这个线程将被重新创建;如果有很多 新的线程,增加这个值可以改善系统性能。通过比较 Connections 和 Threads_created 状 态的变量,可以看到这个变量的作用。设置规则如下:1GB 内存配置为 8,2GB 配置为 16, 3GB 配置为 32,4GB 或更高内存,可配置更大。
(19)thread_concurrency = 8
设置 thread_concurrency 值的正确与否,对 MySQL 的性能影响很大,在多个 CPU(或多 核)的情况下,错误设置了 thread_concurrency 的值,会导致 MySQL 不能充分利用多 CPU(或多核),出现同一时刻只能一个 CPU 在工作的情况。thread_concurrency 应设为 CPU核数的 2 倍。比如有一个双核的 CPU,那么 thread_concurrency 的应该为 4;2 个双核的 cpu,thread_concurrency 的值应为 8。
(20)query_cache_size = 512M
使用 MySQL 的用户,对于这个变量一定不会陌生。前几年的 MyISAM 引擎优化中, 这个参数也是一个重要的优化参数。但随着发展,这个参数也爆露出来一些问题。机器的内 存越来越大,人们也都习惯性的把以前有用的参数分配的值越来越大。这个参数加大后也引 发了一系列问题。首先分析一下 query_cache_size 的工作原理:一个 SELECT 查询在 DB 中工作后,DB 会把该语句缓存下来。当同样的一个 SQL 再次来到 DB 里调用时,DB 在该 表没发生变化的情况下把结果从缓存中返回给 Client。这里有一个关建点,就是 DB 在利用 Query_cache 工作时,要求该语句涉及的表在这段时间内没有发生变更。那如果该表在发 生变更时,Query_cache 里的数据又怎么处理呢?首先要把 Query_cache 和该表相关的语 句全部设置为失效,然后再写入更新。那么如果 Query_cache 非常大,该表的查询结构又 比较多,查询语句失效也慢,一个更新或是 Insert 就会很慢,这样看到的就是 Update 或是 Insert 怎么这么慢了。所以在数据库写入量或是更新量也比较大的系统,该参数不适合分配 过大。而且在高并发,写入量大的系统,建议把该功能禁掉。
(21)query_cache_limit = 4M
指定单个查询能够使用的缓冲区大小,缺省为 1M。
(22)query_cache_min_res_unit = 2k
默认是 4KB,设置值大对大数据查询有好处,但如果查询都是小数据查询,就容易造 成内存碎片和浪费,查询缓存碎片率=Qcache_free_blocks/Qcache_total_blocks100%。 如果查询缓存碎片率超过 20%,可以用 FLUSHQUERYCACHE 整理缓存碎片,或者尝试 减 小 query_cache_min_res_unit 。 如 果 查 询 都 是 小 数 据 量 , 那 么 查 询 缓 存 利 用 率 =(query_cache_size–Qcache_free_memory)/query_cache_size100%。查询缓存利用率在 25%以下,说明 query_cache_size 设置的过大,可适当减小。查询缓存利用率在 80%以上 而且 Qcache_lowmem_prunes>50 的话说明 query_cache_size 可能有点小,要不就是碎 片太多。查询缓存命中率=(Qcache_hits–Qcache_inserts)/Qcache_hits*100%。
(23)default-storage-engine = innodb
默认引擎,现在一般都是 innodb 引擎表居多。
(24)thread_stack = 192K
设置 MySQL 每个线程的堆栈大小,默认值足够大,可满足普通操作。可设置范围为 128K 至 4GB,默认为 192KB。
(25)transaction_isolation = READ-COMMITTED
设定默认的事务隔离级别,READCOMMITTEE 是读已提交。
(26)tmp_table_size = 256M
tmp_table_size 的默认大小是 32M。如果一张临时表超出该大小,MySQL 产生一个 Thetabletbl_nameisfull 形 式 的 错 误 ; 如 果 执 行 很 多 高 级 GROUPBY 查 询 , 增 加 tmp_table_size 值。如果超过该值,则会将临时表写入磁盘。
(27)key_buffer_size = 1024M
指定用于索引的缓冲区大小,增加它可以得到更好的索引处理性能。
(28)read_buffer_size = 2M
MySQL 读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL 会为它分配一段内存缓冲区。read_buffer_size 变量控制这一缓冲区的大小。如果对表的顺 序扫描请求非常频繁,并且认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲 区大小提高其性能。和 sort_buffer_size 一样,该参数对应的分配内存也是每个连接独享。
(29)read_rnd_buffer_size = 256M
MySQL 的随机读(查询操作)缓冲区大小。当按任意顺序读取行时(例如,按照排序顺 序),将分配一个随机读缓存区。进行排序查询时,MySQL 会首先扫描一遍该缓冲,以避免 磁盘搜索,提高查询速度。如果需要排序大量数据,可适当调高该值。但 MySQL 会为每个 客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
(30)bulk_insert_buffer_size = 64M
批量插入数据缓存大小,可以有效提高插入效率,默认为 8M。
(31)skip-name-resolve
禁止域名解析,包括主机名.所以授权的时候要使用 IP 地址。
(32)ft_min_word_len = 1
从 MySQL4.0 开始就支持全文索引功能,但是 MySQL 默认的最小索引长度是 4。如 果是英文默认值是比较合理的,但是中文绝大部分词都是 2 个字符,这就导致小于 4 个字的词都不能被索引。MySQL 全文索引是专门为了解决模糊查询提供的,可以对整篇文章预 先按照词进行索引,搜索效率高,能够支持百万级的数据检索。
下面几个参数时关于 MySQL 二进制日志文件的优化。
(33)log-bin=mysql-bin
打开 MySQL 二进制功能。
(34)binlog_cache_size = 4M
在事务过程中容纳二进制日志 SQL 语句的缓存大小。二进制日志缓存是服务器支持事 务存储引擎并且服务器启用了二进制日志(—log-bin 选项)的前提下为每个客户端分配的内 存。注意:是每个 Client 都可以分配设置大小的 binlogcache 空间。可以通过 MySQL 的以 下 两 个 状 态 变 量 来 判 断 当 前 的 binlog_cache_size 的 状 况 : Binlog_cache_use 和 Binlog_cache_disk_use。
(35)max_binlog_cache_size = 128M
表 示 binlog 能 够 使 用 的 最 大 cache 内 存 大 小 。 执 行 多 语 句 事 务 的 时 候 , max_binlog_cache_size 如 果 不 够 大 的 话 , 系 统 可 能 会 报 出 “Multi-statementtransactionrequiredmorethan’max_binlog_cache_size’bytesofstorage” 的 错误。
(36)max_binlog_size = 1G
Binlog 日志最大值,一般来说设置为 512M 或者 1G,但不能超过 1G。该大小并不能 非常严格控制 Binlog 大小,尤其是当到达 Binlog 比较靠近尾部而又遇到一个较大事务的时 候,系统为了保证事务的完整性,不可能做切换日志的动作,只能将该事务的所有 SQL 都 记录进入当前日志,直到该事务结束。这一点和Oracle的Redo日志有点不一样,因为Oracle 的 Redo 日志所记录的是数据文件的物理位置的变化,而且里面同时记录了 Redo 和 Undo 相关的信息,所以同一个事务是否在一个日志中对 Oracle 来说并不关键。而 MySQL 在 Binlog 中所记录的是数据库逻辑变化信息,MySQL 称之为 Event,实际上就是带来数据库 变化的 DML 之类的 Query 语句。
(37)sync_binlog=1
在 MySQL 中系统默认的设置是 sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性能是最好的,但是风险也是最大的。因为一旦系统 Crash,在 binlog_cache 中的所有 binlog 信息都会被丢失。而当设置为“1”的时候最安全,但也是性能损耗最大的设 置。因为当设置为 1 的时候,即使系统 Crash,也最多丢失 binlog_cache 中未完成的一个 事务,对实际数据没有任何实质性影响。从以往经验和相关测试来看,对于高并发事务的系 统来说,“sync_binlog”设置为 0 和设置为 1 的系统写入性能差距可能高达 5 倍甚至更多。
(38)binlog_format=mixed
默认使用 statement 模式,基于 SQL 语句的复制,另外一种是基于行的复制,为提升 效率,可以将以上两种模式混合使用。一般的复制使用 STATEMENT 模式保存 binlog,对 于 STATEMENT 模式无法复制的操作使用 ROW 模式保存 binlog,MySQL 会根据执行的 SQL 语句选择日志保存方式。
(39)expire_logs_days = 7
二进制日志只留存最近 7 天,不用人工手动删除。
(40)log-slave-updates
这条参数只读主从架构适用,当从库 log_slave_updates 参数没有开启时,从库的 binlog 不会记录来源于主库的操作记录。只有开启 log_slave_updates,从库 binlog 才会记录主库 同步的操作日志。
(41)slow_query_log
打开慢查询日志。
(42)slow_query_log_file=slow.log
慢查询日志文件位置。
(43)long_query_time = 2
记录超过 2 秒的 SQL 查询。 关于引擎是 innodb 的优化如下:
(44)innodb_additional_mem_pool_size = 64M
这个参数用来设置 InnoDB 存储的数据目录信息和其它内部数据结构的内存池大小,类 似于 Oracle 的 library cache。这不是一个强制参数,可以被突破。
(45)innodb_buffer_pool_size = 20480M
用于缓存索引和数据的内存大小,这个选项的值越多越好, 数据读写在内存中非常快, 减少了对磁盘的读写。当数据提交或满足检查点条件后才一次性将内存数据刷新到磁盘中。 然而内存还有操作系统或数据库其他进程使用,推荐设置 innodb-buffer-pool-size 为服务器 总可用内存的 75%。 若设置不当, 内存使用可能浪费或者使用过多。 对于繁忙的服务器, buffer pool 将划分为多个实例以提高系统并发性,减少线程间读写缓存的争用。buffer pool 的大小首先受 innodb_buffer_pool_instances 影响,当然影响较小。
(46)innodb_data_file_path = ibdata1:1024M:autoextend
用 来 指 定 innodb tablespace 文 件 , 如 果 我 们 不 在 my.cnf 文 件 中 指 定 innodb_data_home_dir 和 innodb_data_file_path 那么默认会在 datadir 目录下创建 ibdata1 作为 innodb tablespace。
(47)innodb_file_io_threads = 4
文件 IO 的线程数,一般为 4,但是在 Windows 下,可以设置得较大。
(48)innodb_thread_concurrency = 8
服务器有几个 CPU 就设置为几,建议用默认设置,一般为 8。
(49)innodb_write_io_threads = 8
InnoDB 使用后台线程处理数据页上写 I/O(输入输出)请求的数量。一般设置为 CPU 核数,比如 CPU 是 2 颗 8 核的,可以设置为 8。
(50)innodb_read_io_threads = 8
InnoDB 使用后台线程处理数据页上读 I/O(输入输出)请求的数量。一般设置为 CPU 核数,比如 CPU 是 2 颗 8 核的,可以设置为 8。
(51)innodb_flush_log_at_trx_commit = 2
如果将此参数设置为 1,将在每次提交事务后将日志写入磁盘。为提高性能,可以设置 为 0 或 2,但要承担在发生故障时丢失数据的风险。设置为 0 表示事务日志写入日志文件, 而日志文件每秒刷新到磁盘一次。设置为 2 表示事务日志将在提交时写入日志,但日志文 件每次刷新到磁盘一次。
(52)innodb_log_buffer_size = 16M
此参数确定日志文件所用的内存大小,以 M 为单位。缓冲区更大能提高性能,但意外的故障将会丢失数据。MySQL 开发人员建议设置为 1-8M 之间。
(53)innodb_log_file_size = 256M
此参数确定数据日志文件的大小,以 M 为单位,较大的值可以提高性能,但也会增加 恢复故障数据库所需的时间。
(54)innodb_log_files_in_group = 3
#为提高性能,MySQL 可以以循环方式将日志文件写到多个文件。
(55)innodb_file_per_table = 1
独享表空间(关闭)。
(56)innodb_max_dirty_pages_pct = 90
Buffer_Pool 中 Dirty_Page 所 占 的 数 量 , 直 接 影 响 InnoDB 的 关 闭 时 间 。 参 数 innodb_max_dirty_pages_pct 可以直接控制了 Dirty_Page 在 Buffer_Pool 中所占的比率, 而且幸运的是 innodb_max_dirty_pages_pct 是可以动态改变的。所以,在关闭 InnoDB 之 前先将 innodb_max_dirty_pages_pct 调小,强制数据块 Flush 一段时间,就能够大大缩短 MySQL 关闭的时间。
(57)innodb_lock_wait_timeout = 120
InnoDB 有其内置的死锁检测机制,能导致未完成的事务回滚。但是,如果结合 InnoDB 使用 MyISAM 的 locktables 语句或第三方事务引擎,InnoDB 就无法识别死锁。为消除这种 可能性,可以将 innodb_lock_wait_timeout 设置为一个整数值,设置 MySQL 在允许其他事 务修改那些最终受事务回滚的数据之前要等待多长时间(秒数)。
(58)innodb_open_files = 8192
innodb 打开文件句柄数。
关于引擎是 myisam 的优化如下:
(59)myisam_sort_buffer_size = 128M
MyISAM 表发生变化时重新排序所需的缓冲大小。
(60)myisam_max_sort_file_size = 10G
MySQL 重建索引时所允许的最大临时文件的大小(当 REPAIR,ALTERTABLE 或者LOADDATAINFILE)。如果文件大小比此值更大,索引会通过键值缓冲创建(更慢)。
(61)myisam_repair_threads = 1
如果一个表拥有超过一个索引,MyISAM 可以通过并行排序使用超过一个线程去修复。 这对于拥有多个 CPU 以及大量内存情况的用户是一个很好的选择。
(62)myisam_recover
自动检查和修复没有适当关闭的 MyISAM 表。
3. SQL 方面
(1)关于索引
索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能 加快数据库的查询速度
通过 EXPLAIN 来分析和优化,explain 显示了 MySQL 如何使用索引来处理 select 语句以及连接表。可以选择更好的索引和写出更优化的查询语句,下面先介绍一下 explain 的相关参数:
● possible_keys:显示可能应用在这张表中的索引。
● key: 实际使用的索引。如果为 NULL,则没有使用索引。
● key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好。
● ref:显示索引的哪一列被使用了,如果可能,则是一个常数。
● Extra:关于 MySQL 如何解析查询的额外信息。
既然索引这么好用,是不是可以把所有的字段都建上索引呢?索引并不是越多越好,索 引是要消耗资源的,有些字段信息不经常查询却建立索引反而影响效率。一个表拥有的索引 越多,插入和删除的速度越慢。就好像一本书如果把书中出现的人名、地名等都来建目录, 目录可能占据整本书的 1/3,而且读者常用的是文章标题目录,这样反而不好,索引是根据 具体的需求来合理的建立。
(2)优化分页
举例说明:统计 EXAM_RESULT_SKILL_72 数据,做一个列表,由于数据太多分页显 示,一页 10 个。正常思路从前往后数 10 个为一组。数据越多查询时间越长。
● 比如有一名为ID的列,其中ID是连续的,就可以算出来起始的位置。然后再次查询时间缩短了很多
● 如果ID不是连续的 ,可以把ID直接拿出来再通过ID查询,最后再通过 ID 查出一页数据的时间
(3)GROUP BY 优化
GROUP BY 的字段建立索引之后,临时表和排序都不见了
总结:实际工作中谨慎的使用 group by 。建立索引时,对 group by 后面的字段建立索 引往往会有惊喜的效果。
4. MySQL 架构方面
从字面的含义上讲就是将一个 MySQL 服务器变成多个 MySQL 服务器并提供服务。最 简单的就是主从架构,主库提供写入、从库提供查询。中间件可以采用第三方开源软件(自带读写分离功能),也可以是开发人员从业务层面进行拆分,然后通过 Haproxy 这种软件 进行代理。常用的架构有主从、主主、一主多从、多主多从等等。不管使用哪一种架构,都 离不开三个核心的原则。
(1)主库写入,从库只读。
(2)多个 MySQL 数据库里面的数据必须一样,数据之间同步尽量缩小到无延迟。
(3)防止主主之间数据脑裂。