【VPS 进阶玩法精选 011】VPS 上 MySQL / PostgreSQL 性能调优实战:1GB~2GB 小内存极限优化与内存档位参数表

从 innodb_buffer_pool_size、shared_buffers 内存分配到 max_connections、慢查询日志、swap/zram 配合,手把手教你把 MySQL 和 PostgreSQL 跑在小内存 VPS 上。附真实配置片段、调优命令和按 1GB/2GB/4GB/8GB 档位划分的推荐参数表。

延伸阅读

更多相关攻略推荐:【内存技术 01】DDR4 还是 DDR5?2026 年内存涨价背景【VPS 硬件选型指南 (CPU 篇) 02】AMD EPYC vs【跑分解读 01】别被商家的虚假宣传骗了!VPS 性能跑分全指南:Y【VPS 硬件选型指南 (CPU 篇) 03】VPS 性价比怎么算?【VPS 进阶玩法精选 013】Windows VPS 授权与安装完

为什么在 VPS 上必须专门调优数据库

很多新手在 VPS 上直接 apt install mysql-serverapt install postgresql 之后就跑业务,结果要么内存爆满被 OOM Killer 干掉,要么 QPS 上不去、磁盘 I/O 拉满。原因很简单:MySQL 8 和 PostgreSQL 16 的出厂默认配置是按大内存服务器设计的,在 1GB~2GB 这种小内存 VPS 上,默认值要么过于激进(吃掉全部内存),要么过于保守(缓存太小导致频繁读盘)。

本篇不空谈理论,直接给你能在 ContaboHetznerRackNerdVultr 这类 1~8GB 内存的 KVM VPS 上落地的参数。先说结论:1~2GB 内存属于"极限生存"档位,能跑轻量博客、低流量 API 和内部工具,但必须严格按下面的配置收窄;4GB 是 MySQL/PostgreSQL 生产环境的起步甜点;8GB 以上才谈得上从容。

需要强调一个心态:调优不是一次性的,而是"改配置 → 观察 → 再微调"的循环。小内存机器对参数极其敏感,照搬网上的"高性能模板"几乎必然翻车。下面每一档参数都是起点,你要在自己真实负载下用监控数据去收敛,而不是设完就再也不看。另外,数据库和应用同机时,还要给 Nginx、PHP-FPM、SSH、系统守护进程留出至少 256MB 余量,这部分常常被人忽略,结果是数据库没 OOM、SSH 却被挤到连不上。

第一步:先摸清家底(内存、磁盘 I/O、当前占用)

动手改配置前,先确认你到底有多少可用内存、磁盘是 SSD 还是 NVMe、数据库现在吃了多少。三个命令就够了:

free -h
swapon --show
lsblk -o NAME,ROTA,SIZE,MODEL   # ROTA=0 表示 SSD/NVMe

再测一下磁盘顺序读写,判断是不是 NVMe(小内存 VPS 上 NVMe 对数据库帮助极大,random_page_cost 可以直接从默认的 4.0 降到 1.1):

fio --name=randread --ioengine=libaio --rw=randread --bs=4k --numjobs=4 --size=1G --runtime=60 --group_reporting

看 MySQL 当前缓冲池有没有生效、命中率如何:

mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
mysql -e "SHOW STATUS LIKE 'Innodb_buffer_pool_read%';"

Innodb_buffer_pool_readsInnodb_buffer_pool_read_requests 的比值越小越好,比值高说明缓冲池太小、经常回磁盘读。

MySQL 在小内存 VPS 上的核心调优

1. innodb_buffer_pool_size:最重要的一个参数

缓冲池是 InnoDB 缓存数据和索引的地方,是 MySQL 内存里最大的消费者。经验法则是设为物理内存的 50%~60%,给 OS 和其他进程(PHP-FPM、Nginx、SSH)留出空间。注意 MySQL 8 默认会"自动调大"缓冲池,在 2GB 机器上可能直接占掉 1GB 以上,导致别的进程被挤爆。

# /etc/mysql/mysql.conf.d/mysqld.cnf  (MariaDB 在 /etc/mysql/mariadb.conf.d/50-server.cnf)
[mysqld]
innodb_buffer_pool_size = 1G          # 2GB 机器:约 50%~60%
innodb_buffer_pool_instances = 1      # 缓冲池 < 1GB 时用单实例,多实例反而增加开销

1GB 机器就降到 256M,并配合单实例:

[mysqld]
innodb_buffer_pool_size = 256M
innodb_buffer_pool_instances = 1

2. max_connections:别给每个连接都留内存

默认 151 个连接对 Dedicated 服务器合理,但对小内存 VPS 太高——每个连接都会吃几 MB 的排序/读缓冲。低流量应用 50 足够,单应用开发环境甚至 25 即可。配合应用层连接池(如 HikariCP、ProxySQL)效果更好。

[mysqld]
max_connections = 50

3. 关闭 performance_schema,省下 100~200MB

这是诊断用的内存表,小内存机器上性价比极低。线上排查可以改用慢查询日志和 pt-query-digest。

[mysqld]
performance_schema = OFF

4. 收紧每会话缓冲与临时表

[mysqld]
sort_buffer_size = 512K
join_buffer_size = 512K
read_buffer_size = 512K
read_rnd_buffer_size = 512K
tmp_table_size = 64M
max_heap_table_size = 64M
innodb_log_buffer_size = 8M

5. 打开慢查询日志,揪出真凶

光调内存不够,慢 SQL 才是性能黑洞。开启慢查询日志,超过 1 秒的记录下来:

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

改完先校验语法再重启:

mysqld --validate-config
systemctl restart mysql
# MariaDB 用: systemctl restart mariadb

PostgreSQL 在小内存 VPS 上的核心调优

1. shared_buffers:PostgreSQL 自己的页缓存

PostgreSQL 出厂默认非常保守,shared_buffers 往往只有 128MB。经验值设为物理内存的 25%,超过 25% 收益递减(因为 Linux 内核页缓存也在缓存同样的块)。2GB 机器设 512MB,1GB 机器设 256MB 甚至 128MB。

# /etc/postgresql/16/main/postgresql.conf  (用 SHOW config_file; 确认实际路径)
shared_buffers = 512MB          # 2GB 机器:约 25%
effective_cache_size = 1500MB   # 约 75%,告诉规划器 OS+PG 一共能热多少数据

2. work_mem:最容易 OOM 的陷阱

这是每个排序/哈希节点的内存预算,不是每连接!一条带 3 个排序节点的查询会吃掉 3 倍 work_mem,再乘以并发数就可能瞬间 OOM。小内存机器上务必保守:

work_mem = 8MB                  # 2GB 机器
# work_mem = 4MB                # 1GB 机器更保守
maintenance_work_mem = 128MB    # VACUUM / CREATE INDEX 用,1GB 机器降到 64MB

3. 降低 max_connections,用 PgBouncer 扛并发

每个 PG 连接要占 5~10MB,100 个连接还没跑查询就吃掉 0.5~1GB。降到 20~50,再用 PgBouncer 在事务级别复用连接:

max_connections = 50
checkpoint_completion_target = 0.9
random_page_cost = 1.1          # SSD/NVMe 环境从 4.0 降到 1.1,让规划器更爱用索引

安装并配置 PgBouncer(事务池模式最省内存):

sudo apt install pgbouncer
# /etc/pgbouncer/pgbouncer.ini
[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb
[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
pool_mode = transaction
default_pool_size = 25
max_client_conn = 200

4. 慢查询日志与热点分析

log_min_duration_statement = 200   # 记录超过 200ms 的语句
log_connections = on
log_disconnections = on

找出真凶用 EXPLAIN 看缓冲命中,再用 pg_stat_statements 定位总耗时最高的 SQL:

sudo -u postgres psql -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;"
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE user_id = 42 ORDER BY created_at DESC;

小内存(1GB~2GB)VPS 的极限优化与 swap/zram

1~2GB 机器上,数据库 + 应用同机,物理内存经常不够。swap/zram 是你的最后一道防线,但用错方式反而拖死性能。要点:

  • 优先用 zram 而不是传统磁盘 swap。zram 用压缩内存当交换区,速度比磁盘 swap 快几个数量级,特别适合内存紧张的小 VPS。多数现代发行版(Ubuntu 22.04+/Debian 12+)已默认启用 zram,可用 zramctl 查看。
  • 传统磁盘 swap 要设 swappiness 偏低,避免数据库频繁被换出。建议 vm.swappiness=10,并设 vm.vfs_cache_pressure=50 保护目录缓存。
  • 给 MySQL 加内存上限保护:通过 systemd 的 MemoryMax 限制,避免它把整台机器拖垮。
# 查看 zram
zramctl
swapon --show

# 调低 swappiness(写入 /etc/sysctl.d/99-vps.conf)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-vps.conf
echo 'vm.vfs_cache_pressure=50' | sudo tee -a /etc/sysctl.d/99-vps.conf
sudo sysctl --system

# 给 MySQL 套内存上限(/etc/systemd/system/mysql.service.d/limits.conf)
[Service]
MemoryMax=1500M

对 PostgreSQL,用 vm.overcommit_memory=2 + vm.overcommit_ratio 防止 OOM,并配置 oom_score_adj 让 postmaster 不被优先杀掉:

echo 'vm.overcommit_memory=2' | sudo tee -a /etc/sysctl.d/99-vps.conf
sudo sysctl --system
sudo systemctl edit postgresql
# 在编辑器中加入:
[Service]
OOMScoreAdjust=-500

不同内存档位的推荐参数表

下面是经过多个小内存 VPS 实测的推荐起点值。所有档位都假设数据库与应用同机,请按实际负载微调(切忌直接照搬后不监控)。

内存档位MySQL innodb_buffer_pool_sizeMySQL max_connectionsPG shared_buffersPG work_memPG effective_cache_sizePG max_connections
1GB256M30~50256M4MB512M20~30
2GB1G50~100512M8MB1500M50
4GB2G1501GB16MB3GB100
8GB4~5G3002GB32~64MB6GB200

小内存档位额外建议:performance_schema=OFF(MySQL)、pgbouncer 事务池(PG)、开启 zram、关闭不需要的二进制日志(测试环境)。调优后用 free -h 和数据库内部状态观察,命中率上去了、swap 几乎不波动,才说明配置对了。

选型参考:四家 VPS 厂商的内存与价格(2026)

调优能救小内存,但选对机器更省心。下面是 2026 年四家厂商的内存档位与月付/年付参考(价格随活动波动,以官网为准):

  • RackNerd:KVM 架构,SSD RAID-10,1Gbps。1GB 年付约 $21.99/年(约 $1.8/月),2GB 约 $35.99/年,4GB 约 $59.99/年;机房集中在洛杉矶、圣何塞、达拉斯等美国节点,支持支付宝/PayPal,是极限优化练手的首选便宜货。
  • Hetzner:CX 系列共享 vCPU,NVMe,20TB 流量。CX22(2 vCPU/4GB/40GB NVMe)约 €4.35/月(~$4.65),CX32(4 vCPU/8GB)约 €7.59/月;德国/芬兰/美东/新加坡机房,DDoS 防护和 IPv4/IPv6 免费,性价比甜点档。
  • Contabo:同价位给的 RAM 最多。Cloud VPS 10(3 vCPU/8GB/75GB NVMe/32TB)约 €4.50/月,VPS S(4 vCPU/8GB)约 $4.99~7.99/月;缺点是非独享 CPU、SLA 99.0%、入站免费出站 32TB,适合 RAM 是瓶颈的数据库场景。
  • Vultr:全球 32+ 机房、按小时计费。Regular 1GB 约 $5~6/月,2GB 约 $10~12/月,4GB 约 $20~24/月;High Frequency(AMD EPYC + NVMe)单核更强,新用户有 $100~300 试用额度,适合需要就近低延迟节点的业务。

调优之后如何验证效果(监控与回滚)

改完配置不是终点,必须验证是否真的变快、是否稳定。最实用的两个观察点是内存和缓冲命中率。用 free -h 看 available 是否长期为正、swap 是否几乎不动;用数据库自带状态看缓存命中。不要只信"感觉快了",要用数字说话。

# MySQL 缓冲池命中率(结果越接近 1 越好)
mysql -e "SELECT 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) AS hit_rate FROM (SELECT VARIABLE_VALUE AS Innodb_buffer_pool_reads FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME='Innodb_buffer_pool_reads') r, (SELECT VARIABLE_VALUE AS Innodb_buffer_pool_read_requests FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME='Innodb_buffer_pool_read_requests') q;"

PostgreSQL 侧用 pg_stat_database 看 blk_hit 占比,配合 pg_stat_statements 的 mean_exec_time 找出仍需优化的慢 SQL。任何改动都建议先 cp 备份原配置(例如 postgresql.conf.bak、mysqld.cnf.bak),一旦重启后连不上或负载异常,立刻回滚并对比前后指标。

还有一个常被忽视的点:应用层必须配合。再好的数据库参数也救不了 SELECT *、缺失索引和 N+1 查询。上线前用 EXPLAIN 逐条确认执行计划走了索引,给 WHERE、JOIN、ORDER BY 字段补上索引,并把热点数据放进 Redis,这往往比继续加内存收益更大。调优的尽头永远是从"堆资源"转向"改写法"。

💡 延伸阅读:关于架构与基础设施的更多深潜指南,请前往 VPS 主题导读中心 (Hub) 获取全盘策略。