在 2 核 4G 的服务器上运行 MySQL 8.0,核心优化思路是严格控制内存占用、减少上下文切换、避免磁盘 I/O 瓶颈。以下是针对 CentOS/Ubuntu 的系统级和数据库级优化方案:
一、系统层面优化(OS Tuning)
1. 关闭不必要的服务
# Ubuntu
sudo systemctl disable bluetooth hddtemp thermald
# CentOS
sudo systemctl disable firewalld # 如用 iptables/nftables 替代
2. 调整内核参数(/etc/sysctl.conf)
vm.swappiness = 10 # 降低交换分区使用倾向
vm.vfs_cache_pressure = 50 # 优先缓存文件而非 inode/dentry
net.core.somaxconn = 1024 # 提升连接队列深度
net.ipv4.tcp_max_syn_backlog = 2048
kernel.shmmax = 2147483648 # 共享内存上限(4G 服务器建议设为物理内存一半左右)
应用生效:
sudo sysctl -p
3. 文件系统挂载优化
在 /etc/fstab 中添加 noatime,nodiratime 选项(减少写入元数据操作):
/dev/sda1 / ext4 defaults,noatime,nodiratime 0 1
注意:需确保
/var/lib/mysql所在分区也添加该选项。
4. CPU 频率调节
将 CPU 模式设为 performance(避免动态降频导致延迟波动):
# Ubuntu/CentOS 通用
sudo apt install linux-cpupower # Ubuntu
sudo yum install kernel-tools # CentOS
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
可加入开机启动脚本或 systemd 服务。
二、MySQL 8.0 配置优化(my.cnf 关键项)
编辑 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf,在 [mysqld] 下添加:
[mysqld]
# 基础设置
user = mysql
basedir = /usr
datadir = /var/lib/mysql
port = 3306
socket = /tmp/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid
# 字符集(推荐 utf8mb4)
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# 内存管理(核心!4G 总内存,留给 OS + InnoDB Buffer Pool ≈ 2.5~3G)
innodb_buffer_pool_size = 2G # 占物理内存 50%~60%
innodb_log_file_size = 512M # 日志文件大小(影响刷新频率)
innodb_flush_method = O_DIRECT # 绕过 OS 缓存,避免双重缓冲
innodb_flush_log_at_trx_commit = 1 # 保证事务安全(生产环境必须为 1;若追求性能可试 2,但有风险)
# 连接与线程
max_connections = 150 # 根据实际并发调整,过高会耗尽内存
thread_stack = 256K
thread_cache_size = 32
wait_timeout = 300
interactive_timeout = 300
# 查询缓存(MySQL 8.0 已移除 query cache,无需配置)
# skip-query-cache # 默认已禁用
# InnoDB 其他关键参数
innodb_flush_neighbors = 0 # 减少页内碎片 I/O
innodb_io_capacity = 400 # SSD 可设 2000+,HDD 保持 200–400
innodb_io_capacity_max = 800
innodb_purge_threads = 1 # 单核机器建议 1,避免过多线程争抢
innodb_thread_concurrency = 0 # 自动管理(现代版本推荐)
# 临时表与排序
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 2M # 每个连接独立分配,不宜过大
read_buffer_size = 2M
read_rnd_buffer_size = 2M
# 日志与监控
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2 # 记录超过 2 秒的查询
log_queries_not_using_indexes = ON
# 安全加固
local_infile = OFF
skip-symbolic-links = ON
✅ 关键原则:
innodb_buffer_pool_size不要超过物理内存的 60%,预留至少 1G 给 OS 和其他进程(如 Nginx、PHP-FPM)。sort_buffer_size等每连接参数 ×max_connections可能达数十 MB,需控制总和 ≤ 500MB。
三、实践建议与监控
1. 启用慢查询分析
- 定期分析
slow_query_log,使用mysqldumpslow或pt-query-digest定位瓶颈。 - 对高频慢查询添加索引(尤其
WHERE,ORDER BY,JOIN字段)。
2. 使用 mysqltuner.pl 自动诊断
# Ubuntu
sudo apt install perl libdbi-perl libdigest-hmac-perl libio-socket-ssl-perl
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
sudo perl mysqltuner.pl --host localhost --user root --password
# CentOS
yum install perl-DBI perl-Digest-HMAC perl-IO-Socket-SSL
# 同上下载运行
根据输出动态调整参数。
3. 监控工具推荐
htop/top:观察 CPU、内存、swap 使用。iotop:检查磁盘 I/O 热点。mysqladmin extended-status或 Prometheus + mysqld_exporter 做长期监控。
4. 避免常见陷阱
- ❌ 不启用
query_cache(MySQL 8.0 已移除)。 - ❌ 不设
innodb_buffer_pool_size过小(<1G)或过大(>3G),易触发 swap。 - ❌ 允许大量临时表溢出到磁盘(调高
tmp_table_size+ 加索引减少排序)。 - ❌ 未开启
O_DIRECT导致 OS 缓存与 InnoDB 缓存重复,浪费内存且增加 I/O。
四、进阶可选(视需求)
| 场景 | 建议 |
|---|---|
| 读多写少 | 考虑主从复制,只读节点分担负载 |
| 高并发短连接 | 启用 connection_control_min_connection_delay + 应用层连接池(如 HikariCP) |
| 大数据量表 | 分区表(Range/List)、历史数据归档 |
| 极致性能 | 评估是否迁移至 MariaDB 10.10+(部分场景更轻量)或使用云数据库托管服务 |
✅ 最后验证步骤:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Slow_queries';
确保无频繁 swap、buffer pool hit rate > 95%、慢查询数量可控。
如需进一步定制(如 Docker 部署、容器化资源限制、或与 Nginx/PHP 协同调优),可提供具体架构细节继续深入。
CLOUD技术笔记