走啊走
奋斗

如何优化MySQL在2核2G服务器上的内存使用?

服务器价格表

2 核 2G 跑 MySQL,核心矛盾就一个:内存不够用,但数据库又必须得活。这时候别想着搞什么高并发架构优化,首要任务是“活着”,其次才是“快”。

直接上干货,按优先级操作:

1. 死磕 innodb_buffer_pool_size

这是命门。默认配置通常会让 MySQL 占用几百兆甚至更多,但在 2G 机器上,OS 和 MySQL 会抢着吃内存,一旦触发 Swap(交换分区),性能直接归零。

  • 怎么设:把 innodb_buffer_pool_size 设为物理内存的 50%~60%。也就是 1G 左右。
    • 如果只跑纯 MySQL,可以稍微给到 70%(约 1.4G)。
    • 如果还要跑 Nginx、PHP/Java 应用,那只能给 40%-50%(800M-1G)。
  • 为什么:InnoDB 主要靠这个池子缓存数据和索引。池子太小,磁盘 IO 飙升;池子太大,系统一紧张就把 OOM Killer 请来了。
  • 注意:千万别开 innodb_log_file_size 太大,默认 48M 够用就行,或者微调,别占太多内存。

2. 关掉所有没用的东西

很多配置在 2G 机器上是累赘。打开 my.cnfmysql.cnf,检查并调整以下项:

如何优化MySQL在2核2G服务器上的内存使用?

  • 关闭查询缓存 (query_cache_type = 0):MySQL 5.7+ 已经废弃了,8.0 直接砍了。即使还在用 5.7,也建议关掉。这东西在低内存下不仅没用,还会造成严重的锁竞争。
  • 限制连接数 (max_connections):默认通常是 151。在 2G 机器上,每个连接起步就是几 MB 内存。把它压到 50-100 之间。除非你是做长连接池,否则不需要那么多并发。
  • 临时表内存 (tmp_table_size & max_heap_table_size):这两个参数决定了内存中临时表的上限。默认可能很大,建议都设为 64M128M。超过这个大小强制落盘到磁盘,虽然慢点,但能防止内存爆炸。
  • 排序缓冲区 (sort_buffer_size, read_rnd_buffer_size):这些是每个连接独享的!千万别设大。每个连接默认可能几 MB,100 个连接就是几百 MB。把它们统统降到 32K – 64K 级别。只要不出现大量全表扫描 + 排序,这点内存够用了。

3. 开启 Swap,但要防“假死”

2G 内存跑数据库,必须 配 Swap 分区(虚拟内存),哪怕只有 2G。

  • 作用:当物理内存爆满时,Linux 会把不常用的页换出去,避免直接 OOM 杀掉进程。
  • 关键设置:修改 /etc/sysctl.conf,将 vm.swappiness 调小,比如设为 10
    • 默认是 60,太爱用 Swap 了,会导致频繁读写磁盘,卡成狗。
    • 设为 10,让系统优先挤占物理内存,实在装不下了再动 Swap。这样能保证大部分时间在物理内存里跑,只有极端情况才进 Swap。

4. 监控与观察

改完配置重启服务后,别急着上线业务。先跑几天看看:

  • 看状态show status like 'Innodb_buffer_pool_pages%'; 关注脏页比例。
  • 看慢查询:开启慢查询日志(long_query_time 设为 1 秒即可),找出那些没走索引的 SQL。在 2G 机器上,一条烂 SQL 就能拖垮整个库。
  • 看内存曲线:用 free -m 或者 top 盯着看。如果 Swap 使用量一直很高,说明还是内存不够,要么继续调小其他参数,要么考虑删数据、归档历史数据。

5. 终极方案:换个引擎或架构

如果上述操作做完,发现还是扛不住:

  • 表结构优化:把大字段(Text/Blob)单独拆出来存,主表只留 ID 和索引。减少单行数据体积,能塞进 Buffer Pool 的数据就多了。
  • 分库分表:如果数据量真的到了千万级,2G 硬扛是不可能的。把老数据归档到冷存储,或者拆分到多个小实例上。
  • 升级硬件:说实话,2 核 2G 现在连入门级云数据库都勉强。如果是生产环境,加钱升级到 4G 内存,性价比比你自己在那调参高得多。

总结一句话:在 2G 环境下,MySQL 的核心策略是 “保命”。牺牲一点并发能力,牺牲一点查询速度,换取系统不崩溃。把内存留给 InnoDB 缓冲池,把连接数掐死,把临时表限制住,这就是最务实的优化。