阿里云 1 核 2G(1 vCPU, 2GB RAM)的 ECS 实例运行 MySQL 确实属于资源极度受限的场景。在这种配置下,MySQL 很容易因为内存不足触发 Swap 交换、CPU 争用或连接数限制而卡顿。
要解决这个问题,建议按照以下优先级进行排查和优化:
1. 紧急止损:检查是否开启 Swap
这是最常见的原因。当物理内存耗尽时,Linux 会启用 Swap 分区,导致磁盘 I/O 飙升,数据库响应瞬间变慢。
- 检查命令:
free -h和vmstat 1。如果si/so(swap in/out) 有数值且持续较高,说明正在使用 Swap。 - 解决方案:
- 临时方案:关闭 Swap(仅用于测试,重启后失效):
sudo swapoff -a。 - 根本方案:必须升级内存。对于生产环境的 MySQL,强烈建议至少升级到 4G 内存(2 核 4G 是 MySQL 的起步推荐配置)。如果无法升级,请考虑迁移到轻量应用服务器(Lightweight Application Server),其通常针对 Web 场景优化,性价比更高。
- 临时方案:关闭 Swap(仅用于测试,重启后失效):
2. 核心优化:调整 my.cnf 参数
在 2G 内存的限制下,必须严格限制 MySQL 占用的内存,避免 OOM(Out Of Memory)杀死进程。请将 /etc/my.cnf 中的 [mysqld] 部分修改为以下保守配置:
[mysqld]
# 基础设置
basedir = /usr/local/mysql
datadir = /data/mysql
port = 3306
socket = /tmp/mysql.sock
# 关键内存参数 (总和需控制在 1.5G 以内,留 0.5G 给操作系统和其他进程)
max_connections = 50 # 限制最大连接数,防止并发过高撑爆 CPU
innodb_buffer_pool_size = 512M # 核心:InnoDB 缓存大小,设为物理内存的 25%-30%
key_buffer_size = 64M # MyISAM 索引缓冲,若只用 InnoDB 可设小点
# 其他关键参数
thread_cache_size = 16
query_cache_size = 0 # MySQL 5.7+ 已废弃,8.0 直接移除,务必设为 0
tmp_table_size = 16M
max_heap_table_size = 16M
table_open_cache = 200
sort_buffer_size = 128K # 调小,防止单个排序操作占用过多内存
read_buffer_size = 128K
read_rnd_buffer_size = 128K
innodb_log_file_size = 128M
innodb_flush_log_at_trx_commit = 2 # 权衡性能与安全性,设为 2 可提升写入速度(掉电可能丢一秒数据)
log_bin = mysql-bin
expire_logs_days = 7
slow_query_log = 1
long_query_time = 2 # 记录超过 2 秒的慢查询
slow_query_log_file = /var/log/mysql/slow.log
注意:修改配置后需重启 MySQL (systemctl restart mysqld) 生效。
3. SQL 与架构层面优化
硬件瓶颈无法通过代码完全解决,但可以减少无效负载:
- 开启慢查询日志:查看
slow_query_log,定位执行时间长的 SQL 语句。 - 添加索引:确保
WHERE,ORDER BY,JOIN字段上有合适的索引。在低配机器上,全表扫描是致命的。 - 避免大事务:不要一次性更新或删除大量数据,分批次处理。
- 读写分离:如果业务允许,将报表类、统计类的复杂查询路由到只读副本或从库,减轻主库压力。
4. 系统级优化
- 禁用不必要的服务:关闭防火墙以外的非核心服务(如 Nginx/Apache 如果不需要可以卸载或减少并发)。
- 使用 SSD:确认你的 ECS 使用的是云盘(ESSD 或高效云盘)。机械硬盘在 1 核环境下几乎无法支撑 MySQL 的随机读写。
- 监控工具:安装
htop或zabbix监控 CPU 和内存使用率,观察是否有特定时间段出现峰值。
5. 最终建议:架构调整
如果经过上述优化,业务高峰期依然卡顿,说明 1 核 2G 的物理极限已到。此时只有两条路:
- 升配:将实例升级为 2 核 4G(成本增加不多,但性能会有质的飞跃)。
- 架构拆分:
- 将数据库迁移到 RDS MySQL 基础版(虽然也是按量付费,但 RDS 底层资源隔离更好,且支持自动扩缩容)。
- 或者引入 Redis 作为缓存层,拦截大部分读请求,大幅降低 MySQL 压力。
总结:1 核 2G 跑 MySQL 属于“勉强能跑”的状态。最立竿见影的措施是关闭 Swap并严格限制 innodb_buffer_pool_size,但长期稳定运行的唯一可靠方案是增加内存至 4G或迁移至 RDS。
CLOUD技术笔记