MySQL 的配置参数有几百个,但真正对性能、稳定性和功能有决定性影响的,其实就集中在连接、缓冲池、日志、优化器这几个方面。理解和正确设置这些参数,是数据库调优的基本功。下面逐一拆解。
连接参数
连接参数控制着客户端如何连上 MySQL,以及服务端能同时处理多少连接。配得太小,应用会报“too many connections”;配得太大,服务器资源可能被耗尽。
max_connections
- 作用:允许的最大并发客户端连接数。超过这个数的新连接会被直接拒绝。
- 默认值:151(MySQL 5.7 / 8.0)。
- 配置建议:这个值要根据实际业务并发量和服务器内存来定。每个连接都会占用内存(主要是线程栈和排序缓冲区等),粗略估算,一个连接大约占用 2MB ~ 10MB。如果设置 2000 个连接,光连接就吃掉几 GB 内存。日常实践中,几百到一千是比较常见的范围,不建议一味调大。更好的做法是在应用层使用连接池,复用少量连接,而不是让数据库扛着几万个空闲连接。
- 调整方法:动态修改
SET GLOBAL max_connections = 1000;,但永久生效需要写入配置文件。
max_connect_errors
- 作用:当某个主机连续连接失败次数超过这个值,MySQL 会暂时屏蔽该主机的后续连接请求(报错
Host 'xxx' is blocked)。 - 默认值:100。
- 配置建议:这是防止暴力破解的简单机制。如果你的 API 服务器偶尔因为网络抖动大量连接失败,可能会触发屏蔽,导致服务中断。可以适当调大,比如 1000,或者用
FLUSH HOSTS;手动清除。
thread_cache_size
- 作用:缓存空闲的线程,供新连接复用,避免频繁创建/销毁线程的开销(线程宝贵)。
- 默认值:根据系统自动计算,通常较小。
- 配置建议:通过
SHOW STATUS LIKE 'Threads_created';观察连接创建速率。如果每秒都有大量新线程被创建,就增大这个值。一般设置为max_connections的 10% ~ 20% 即可,比如最大连接 800 时设 128 或 256。
wait_timeout / interactive_timeout
- 作用:
wait_timeout是非交互式连接(如应用连接)空闲多少秒后被自动断开;interactive_timeout是交互式连接(通过 mysql 命令行)的超时。 - 默认值:28800(8 小时)。
- 配置建议:生产环境通常需要缩短,因为大量空闲连接会白白占用资源。建议将
wait_timeout设为 600(10 分钟)或更短,配合连接池的心跳检测使用。
缓冲池参数
InnoDB 的缓冲池(Buffer Pool)是内存中最大的一块缓存,用来存放数据页和索引页。它是 MySQL 读性能的核心,对写入也有直接影响。
innodb_buffer_pool_size
- 作用:缓冲池的总大小。缓冲池缓存了表数据和索引,命中内存则无需磁盘 I/O。
- 默认值:128MB(远远不够生产环境)。
- 配置建议:这是 MySQL 调优中最重要的参数,没有之一。经验法则是设置为可用物理内存的 60% ~ 80%。例如服务器有 64GB 内存,可以分配 48GB ~ 52GB。但前提是给操作系统和其他进程留够内存,否则 MySQL 会触发 OOM。一个常见的检查命令是
SHOW ENGINE INNODB STATUS\G,里面有 Buffer Pool 的命中率Buffer pool hit rate,线上通常要求 99% 以上。如果命中率偏低,优先考虑加大这个参数。 - 注意:8.0 支持动态调整,但建议还是在配置文件中设好并重启生效,避免在线调整时的性能抖动。
innodb_buffer_pool_instances
- 作用:将缓冲池拆分成多个实例,减少多线程并发访问时的内部锁竞争。
- 默认值:8(当
innodb_buffer_pool_size为 1GB 及以上时)。 - 配置建议:一般设置为 4 ~ 8 即可,当缓冲池大于几十 GB 时可适当增加。每个实例的大小不应小于 1GB。
innodb_old_blocks_time
- 作用:新读入缓冲池的数据页最初放在 old 子链表,在
innodb_old_blocks_time毫秒内如果再次被访问,才会移到 young 子链表。这能避免一次性的全表扫描把真正的热数据挤出缓冲池。 - 默认值:1000(毫秒)。
- 配置建议:默认值通常够用。如果你的业务中有比较重的报表类全表扫描,可以适当增大,比如 2000,让热数据保护更严格。
innodb_change_buffer_max_size
- 作用:Change Buffer 用于缓存对二级索引页的修改,从而延迟磁盘写入。它占缓冲池的最大百分比。
- 默认值:25(即缓冲池的 25%)。
- 配置建议:写密集型业务(如大量的 INSERT、UPDATE)可保留默认值或调大到 40,以优化写入性能。读多写少的场景可以调小,把更多内存留给数据缓存。
日志参数
InnoDB 的 Redo Log 和 Binlog 直接关系到事务持久性和崩溃恢复速度,是性能和可靠性之间的一个关键平衡点。
innodb_log_file_size
- 作用:单个 Redo Log 文件的大小。Redo Log 是循环写的,当文件写满时会触发脏页刷盘,可能导致性能抖动或写入停顿。
- 默认值:48MB(5.7)或 96MB(8.0),严重偏小。
- 配置建议:生产环境通常设置为 1GB ~ 4GB。更大的日志文件意味着可以容纳更多未刷盘的脏页,减少频繁的检查点引起的写入停顿。但过大会导致崩溃恢复时扫描 Redo Log 时间变长。调整这个值需要先停止 MySQL 服务,删除旧的 ib_logfile 文件,修改配置后再启动,不能在线修改。
- 估算方法:监控
SHOW ENGINE INNODB STATUS中的Log sequence number增量,估算 30 分钟内 Redo 日志的写入量,将该量值设置为日志文件总大小(两倍于单个文件)的一个参考。
innodb_log_files_in_group
- 作用:Redo Log 文件组中的文件数量。
- 默认值:2。
- 配置建议:保持默认 2 即可。总大小 =
innodb_log_file_size×innodb_log_files_in_group。
innodb_flush_log_at_trx_commit
- 作用:控制 Redo Log 刷盘策略。
0:每秒将日志缓冲写入磁盘并刷盘一次,事务提交不触发。最高性能,但可能丢失 1 秒内的数据。1:每次提交事务都写入磁盘并刷盘。这是完全 ACID 兼容的方式,默认且推荐,但会有磁盘 I/O 压力。2:每次提交事务写入操作系统缓存,每秒刷盘一次。主机宕机可能丢失数据,但 MySQL 进程崩溃不会丢失。- 配置建议:金融、交易等场景必须设为
1。普通业务如果低频写入,也建议1。只有在吞吐量极高且能容忍少量数据丢失的情况下才考虑2或0。
sync_binlog
- 作用:控制 Binlog 刷盘频率。
0:交给操作系统控制,性能最好,可能丢失多个事务的 Binlog。1:每次提交事务就刷盘 Binlog。强一致性配置,配合innodb_flush_log_at_trx_commit=1实现真正的持久化。N:每 N 次事务提交刷盘一次。- 配置建议:需要主从复制和数据可靠性时,必须设为
1。双 1 配置(innodb_flush_log_at_trx_commit=1和sync_binlog=1)是金融级数据库的标配。
expire_logs_days / binlog_expire_logs_seconds
- 作用:Binlog 的自动清理周期。8.0 推荐使用
binlog_expire_logs_seconds(秒级粒度),取代老参数。 - 默认值:30 天。
- 配置建议:按磁盘空间和备份策略来,通常保留 7 ~ 14 天,确保有足够时间在需要时进行基于时间点的恢复,同时避免撑爆磁盘。
优化器参数
优化器参数影响着执行计划的选择,有时候需要微调来避免优化器“走错路”。
optimizer_switch
- 作用:总开关,包含许多子标志,控制优化器是否启用特定优化。例如
index_merge=on、derived_merge=on、use_index_extensions=on等。 - 配置建议:大部分情况下保持默认即可。某些场景下,如果你发现优化器错误地选择了合并索引(index merge),可以临时关闭
index_merge=off来验证。这个参数通常用于针对性调优,不轻易全局改动。
optimizer_search_depth
- 作用:优化器在评估表的连接顺序时,搜索的深度。
- 默认值:62(已经很深)。
- 配置建议:多表连接(7~8 张表以上)时,优化器评估可能的连接顺序会消耗大量时间。如果遇到查询解析时间过长,可以适度减小这个值,例如设为 0(自动选择)或者 5。通常保持默认即可,非必要不改动。
max_seeks_for_key
- 作用:优化器在进行索引选择时,认为扫描一定数量行会超过某个开销阈值的参考值。通常不需要改动。
- 默认值:18446744073709551615(很大,实际等于无限)。
- 配置建议:仅在特定环境中,如果你想故意让优化器偏向于全表扫描而非索引扫描时可能用到,极少需要调整。
join_buffer_size
- 作用:用于普通连接(非索引连接)时的缓冲区大小。当查询涉及全表扫描连接时,会用到这个缓冲区。
- 默认值:256KB。
- 配置建议:如果经常执行没有索引的连接查询(此时
EXPLAIN中 type 为ALL且 Extra 有Using join buffer),可以适当加大如 4MB ~ 16MB。但更好的办法是给连接列创建索引,避免使用 join buffer。注意它是按连接分配的,设太大容易撑爆内存。
sort_buffer_size
- 作用:单个需要排序的会话分配的排序缓冲区大小。
- 默认值:256KB。
- 配置建议:当查询需要文件排序(
Using filesort)时,会使用这个缓冲区。加大可以一次性在内存中完成更多排序,但也要注意它是按需分配的,设得太大(如数十 MB)且并发排序查询多时,内存消耗会爆增。建议保守地设为 1MB ~ 4MB,然后根据SHOW GLOBAL STATUS LIKE 'Sort_merge_passes'增量来判断:如果这个值增长很快,可以适当再调大。
这些参数共同构成了 MySQL 性能调优的主干。实际优化中,很少需要一次性改动十几个参数,往往是围绕着 innodb_buffer_pool_size、日志大小、双 1 配置以及连接相关参数做基础设定,然后再根据具体查询表现细微调整优化器开关。配置文件的注释写得再清楚也不如手动实测和监控,一切以实际环境的表现和业务需求为准。