在 CentOS 7/8 或 Ubuntu 18.04/20.04+ 上部署 MySQL 8.0,生产环境不能只靠默认配置。默认配置偏向于“能跑起来”,而不是“跑得稳、跑得快、睡得香”。
以下我从安全加固和性能调优两个维度,梳理出必须关注的核心参数和配置项。这些是基于大量线上故障复盘和最佳实践总结出来的“硬通货”。
一、 安全加固(Security Hardening)
MySQL 8.0 相比 5.7 在安全性上有很大提升,但如果不手动干预,依然处于“裸奔”状态。
1. 禁用本地文件加载与远程 root
这是最基础的两道防线。
[mysqld]
# 禁止从本地读取文件到数据库,防止攻击者利用 LOAD DATA LOCAL INFILE 读取服务器敏感文件
local-infile=0
# 禁止 root 用户远程登录。root 只能 localhost 访问
allow-suspicious-udfs=0
- 操作建议:创建专用的业务账号(如
app_user),赋予最小权限,严禁使用root连接应用。
2. 强制 SSL/TLS 加密连接
生产环境必须保证数据传输加密,尤其是跨机房或公有云内网通信。
[mysqld]
ssl-ca=/etc/mysql/certs/ca.pem
ssl-cert=/etc/mysql/certs/server-cert.pem
ssl-key=/etc/mysql/certs/server-key.pem
require_secure_transport=ON
- 注意:
require_secure_transport=ON会强制所有新连接使用 SSL。如果客户端不支持 SSL,连接将失败。上线前务必测试好驱动兼容性(JDBC, Go-MySQL-Driver 等均需支持 TLS 1.2+)。
3. 密码策略与插件强化
MySQL 8.0 默认启用了 caching_sha2_password 认证插件,比之前的 mysql_native_password 更安全,但部分旧版驱动可能不兼容。
[mysqld]
# 强制使用 caching_sha2_password
default_authentication_plugin=caching_sha2_password
# 启用密码强度验证插件
plugin_load_add="auth_socket.so" # 如果需要配合操作系统用户认证
- 关键点:确保你的应用程序使用的数据库驱动版本足够新(如 Java JDBC 8.0+, Python mysqlclient 等),否则会因为认证插件不匹配而报错。
4. 限制错误日志泄露信息
默认的错误日志可能会打印 SQL 语句中的敏感信息或堆栈跟踪。
[mysqld]
log_error_verbosity=2 # 降低详细程度,避免记录过多调试信息
二、 性能调优(Performance Tuning)
MySQL 的性能瓶颈通常在于 InnoDB Buffer Pool、磁盘 I/O 和 连接管理。以下是针对 8.0 的核心参数。
1. InnoDB Buffer Pool(内存是王道)
这是最重要的参数。原则:尽可能大,但不要超过物理内存的 70%-80%(预留空间给 OS 和其他进程)。
[mysqld]
innodb_buffer_pool_size=12G # 假设你有 16G 内存,这里设为 12G
innodb_buffer_pool_instances=8 # 每个实例约 1.5G,减少锁竞争
- 为什么设实例数? 当 Buffer Pool 很大时,单线程扫描会造成锁竞争。设置为 CPU 核心数或适当数量(如 8-16)可以并行访问不同区域。
2. Redo Log 与 Binlog 刷盘策略(持久性 vs 性能)
MySQL 8.0 默认 innodb_flush_log_at_trx_commit=1,这意味着每次事务提交都同步刷盘,最安全但最慢。
[mysqld]
# 方案 A:XX级数据,追求绝对安全
innodb_flush_log_at_trx_commit=1
# 方案 B:一般业务,可接受秒级数据丢失风险,性能提升显著
innodb_flush_log_at_trx_commit=2
sync_binlog=1 # Binlog 必须每次提交都刷盘,防止主从复制数据不一致
- 重要提示:如果你使用的是 SSD 且 RAID 卡有电池保护(BBU),可以考虑
innodb_flush_log_at_trx_commit=2并将os_file_flush_method=O_DIRECT或fdatasync优化。对于大多数云厂商,推荐保持1以规避数据丢失风险,除非你能承受极小概率的数据回滚。
3. 连接管理与线程缓存
避免频繁创建/销毁连接带来的开销。
[mysqld]
max_connections=1000 # 根据应用并发量调整,不要设太大导致 OOM
thread_cache_size=64 # 缓存空闲线程,快速响应新连接
performance_schema=ON # 开启性能监控,但生产环境若 CPU 紧张可关闭
- 注意:
max_connections不是越多越好。每个连接都会占用内存(约几 MB 到几十 MB)。如果设了 10000,即使没人连,也可能占满内存。结合连接池(如 HikariCP, Druid)在应用层控制连接数更合理。
4. 查询缓存(Query Cache)—— 已移除!
重要提醒:MySQL 8.0 彻底移除了 Query Cache。不要尝试配置 query_cache_type 或 query_cache_size,它们会被忽略。8.0 依赖更好的索引、Buffer Pool 缓存数据和应用层缓存(Redis/Memcached)。
5. 临时表与排序优化
防止排序操作溢出到磁盘,影响性能。
[mysqld]
tmp_table_size=64M
max_heap_table_size=64M
sort_buffer_size=2M # 每个会话单独分配,别设太大
read_rnd_buffer_size=2M
join_buffer_size=2M # 同样,每个会话分配,仅用于无索引 Join
- 原则:
tmp_table_size和max_heap_table_size应保持一致。较小的sort_buffer_size和join_buffer_size可以避免内存爆炸,因为它们是 per-thread 分配的。
6. 半同步复制(Semi-Sync Replication)—— 高可用必备
如果是主从架构,强烈建议开启半同步复制,防止主库宕机时从库数据落后太多。
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1
rpl_semi_sync_master_timeout=1000 # 超时 1 秒后降级为异步
三、 操作系统层面的关键配置(常被忽视)
MySQL 跑得好不好,一半看 MySQL 配置,一半看 OS 配置。
1. 文件系统挂载选项
确保 /var/lib/mysql 所在的分区挂载了 noatime 和 discard(如果是 SSD)。
# /etc/fstab 示例
/dev/sdb1 /var/lib/mysql ext4 defaults,noatime,discard 0 2
noatime:避免每次读取文件都更新访问时间戳,减少写放大。discard:TRIM 命令支持,延长 SSD 寿命并维持性能。
2. 网络内核参数优化
MySQL 在高并发下容易遇到 TIME_WAIT 堆积或端口耗尽。
# /etc/sysctl.conf
net.ipv4.tcp_tw_reuse=1 # 允许重用 TIME_WAIT sockets
net.ipv4.tcp_fin_timeout=30 # 缩短 FIN-WAIT-2 状态时间
net.core.somaxconn=1024 # 监听队列长度,默认 128 太小,易导致连接拒绝
net.ipv4.ip_local_port_range=10000 65535 # 扩大 ephemeral port 范围
3. 交换分区(Swap)处理
生产环境建议关闭 Swap 或将其优先级调到最低。
# 查看 swap 使用情况
swapon --show
# 如果必须保留,降低优先级
sysctl vm.swappiness=10
- 原因:一旦系统开始使用 Swap,MySQL 性能会断崖式下跌,因为磁盘 I/O 远慢于内存。宁可让 OOM Killer 杀掉进程,也不要让 Swap 拖垮整个服务。
四、 部署后的验证清单
- 检查变量生效:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'ssl_%'; SHOW VARIABLES LIKE 'max_connections'; - 压力测试:
使用sysbench或tpcc-mysql进行基准测试,观察 QPS、TPS、延迟分布(P99/P95)。 - 监控告警:
接入 Prometheus + Grafana 或 Zabbix,重点监控:InnoDB buffer pool hit ratio(应 > 99%)Threads_connectedvsmax_connectionsBinlog disk usageReplication lag(主从延迟)
总结
在生产环境中部署 MySQL 8.0,不要迷信“万能配置”。上述参数是通用基线,具体数值需要根据你的硬件规格(CPU 核数、内存大小、磁盘类型)、业务负载特征(读多写少还是写多读少)和数据量级进行调整。
记住一条铁律:先改配置,再压测,再上线。每一步都要有数据支撑。
云技术博客