my.cnf 核心参数
导学
MySQL 安装后带着一套默认值运行,但生产环境必须根据硬件规格和业务特点调整配置。my.cnf(Linux)或 my.ini(Windows)是 MySQL 的"中枢神经"——它决定服务器用多少内存、允许多少连接、事务如何刷盘。本节聚焦最影响性能和稳定性的核心参数。
配置文件位置与加载顺序
MySQL 5.7 按以下顺序读取配置,后读取的文件覆盖先读取的同名参数:
查看当前服务器实际使用的配置值:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'max_connections';
场景一:内存相关核心参数
innodb_buffer_pool_size
InnoDB 存储引擎的缓冲池,用于缓存表数据和索引。这是 MySQL 5.7 中最重要的性能参数。
[mysqld]
# 服务器内存 8GB 时,建议设为 4GB~6GB(物理内存的 50%~75%)
innodb_buffer_pool_size = 4G
# 如果缓冲池超过 1GB,建议分成多个实例减少锁竞争
innodb_buffer_pool_instances = 4
验证当前设置:
SELECT @@innodb_buffer_pool_size / 1024 / 1024 / 1024 AS size_gb;
| size_gb |
|---|
| 4.0000 |
结果解读:缓冲池越大,热点数据越可能留在内存中,磁盘 I/O 越少。但超过物理内存的 75% 可能导致操作系统换页,反而降低性能。
查看缓冲池命中率
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
| Variable_name | Value |
|---|---|
| Innodb_buffer_pool_reads | 1234 |
| Innodb_buffer_pool_read_requests | 9876543 |
命中率 = 1 - (reads / read_requests)。生产环境应保持在99% 以上。
场景二:连接与线程相关参数
max_connections
允许同时连接的最大客户端数。默认 151,高并发场景需调大。
[mysqld]
max_connections = 500
验证:
SELECT @@max_connections;
| @@max_connections |
|---|
| 500 |
注意:连接数不是越大越好。每个连接消耗内存(thread_cache_size、sort_buffer_size 等累加),500 个连接可能吃掉数 GB 内存。应配合应用层连接池使用。
wait_timeout 与 interactive_timeout
空闲连接自动断开时间(秒),防止应用层连接泄漏撑爆服务器。
[mysqld]
wait_timeout = 600
interactive_timeout = 600
验证当前空闲连接:
SHOW PROCESSLIST;
关注 Command = Sleep 且 Time 很大的连接——如果它们长期不活跃,可能是连接池配置不当或应用未正确关闭连接。
场景三:事务与日志相关参数
innodb_flush_log_at_trx_commit
控制事务日志(redo log)的刷盘策略,直接影响数据安全与性能的平衡。
[mysqld]
# 0:每秒刷盘一次(性能最好,崩溃可能丢1秒数据)
# 1:每次事务提交都刷盘(最安全,默认,性能最差)
# 2:每次事务提交写入 OS 缓存,每秒刷盘(折中)
innodb_flush_log_at_trx_commit = 1
| 取值 | 安全性 | 性能 | 适用场景 |
|---|---|---|---|
| 0 | 低 | 最高 | 非核心日志库,可容忍秒级丢失 |
| 1 | 最高 | 低 | 金融、订单等核心交易(默认) |
| 2 | 中 | 中 | 一般业务,配合 UPS 和 RAID 缓存使用 |
验证:
SELECT @@innodb_flush_log_at_trx_commit;
innodb_log_file_size
单个 redo log 文件的大小。默认 48MB,大事务场景需调大。
[mysqld]
innodb_log_file_size = 256M
innodb_log_files_in_group = 2
注意:修改此参数前必须干净关闭 MySQL,删除旧的 ib_logfile0、ib_logfile1,再启动。否则服务器拒绝启动。
场景四:字符集与排序规则
MySQL 5.7 默认字符集是 latin1,现代应用必须显式改为 utf8mb4。
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# 客户端连接时也使用 utf8mb4
init_connect = 'SET NAMES utf8mb4'
验证:
SHOW VARIABLES LIKE 'character_set%';
| Variable_name | Value |
|---|---|
| character_set_server | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
场景五:慢查询日志(调优必备)
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
验证:
SHOW VARIABLES LIKE 'slow_query%';
| Variable_name | Value |
|---|---|
| slow_query_log | ON |
| slow_query_log_file | /var/lib/mysql/slow.log |
| long_query_time | 2.000000 |
结果解读:执行时间超过 2 秒的 SQL 会被记录到慢查询日志中;未使用索引的查询也会被记录(即使执行很快)。这是性能调优的首要信息来源。
常见误区
| 误区 | 正解 |
|---|---|
"max_connections 越大越好" | 不是。每个连接消耗内存,过大导致 OOM。应配合应用层连接池,通常 200~1000 足够。 |
"innodb_buffer_pool_size 可以设为物理内存的 90%" | 不建议。操作系统和其他进程也需要内存,建议 50%~75%。 |
"修改 my.cnf 后重启立即生效" | 大部分参数需要重启;少数可用 SET GLOBAL 动态修改(如 max_connections),但重启后丢失。 |
"innodb_flush_log_at_trx_commit = 0 不会丢数据" | 会。崩溃时可能丢失最近 1 秒的数据。核心交易必须用 = 1。 |
面试考点
Q:innodb_buffer_pool_size 怎么设?
设为物理内存的 50%~75%。超过 1GB 时配合
innodb_buffer_pool_instances(通常每 1GB 一个实例)减少锁竞争。通过SHOW STATUS LIKE 'Innodb_buffer_pool_read%'计算命中率,应 > 99%。
Q:innodb_flush_log_at_trx_commit 三个取值的区别?
0:每秒刷盘,性能最好但可能丢 1 秒数据;1:每次事务提交刷盘,最安全(默认);2:每次提交写 OS 缓存,每秒刷盘,折中方案。金融交易用 1,日志/统计库可用 0 或 2。
Q:修改 innodb_log_file_size 要注意什么?
必须干净关闭 MySQL,删除数据目录下的
ib_logfile0、ib_logfile1,再启动。MySQL 会自动重建新大小的日志文件。直接修改会导致启动失败。
小结
innodb_buffer_pool_size是最重要的性能参数,建议物理内存的 50%~75%max_connections配合应用层连接池使用,不是越大越好innodb_flush_log_at_trx_commit决定事务安全级别,核心交易必须用 1- 字符集务必设为
utf8mb4,避免中文乱码 - 慢查询日志是性能调优的入口,生产环境必须开启
下一章引子:配置调优让 MySQL 跑得更稳更快,但表结构设计是否合理,决定了数据是否冗余、更新是否异常——这就是数据库范式的意义。