在 1核1G 这种“极限配置”下安装 MySQL,核心矛盾在于:MySQL 默认配置极其吃内存,而 1GB 内存既要维持操作系统基础运行(约 200-300MB),又要留给 Swap 缓冲,还要供给 MySQL 进程。
如果直接套用官方默认配置,服务器会在启动后几分钟内因 OOM(Out of Memory)崩溃或被系统强制杀死进程。因此,最佳实践的核心不是“安装”,而是“极度精简的配置调优”和“存储引擎的选择”。
以下是基于国内主流云环境(阿里云、腾讯云、华为云等)及 CentOS/Ubuntu 系统的实战指南。
一、 前置准备:Swap 是生命线
在 1G 内存服务器上,必须开启 Swap。即使你有 SSD 云盘,Swap 也是防止 MySQL 瞬间崩溃的最后防线。
Ubuntu 设置
# 创建 2GB 的 swap 文件(建议比物理内存大或相等)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
CentOS 7/8 设置
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
注意:调整 Swappiness 参数,让系统在内存紧张时更积极地使用 Swap,而不是直接 Kill 进程。
# 临时生效 sysctl vm.swappiness=10 # 永久写入 /etc/sysctl.conf echo 'vm.swappiness=10' >> /etc/sysctl.conf
二、 版本选择:不要盲目追新
- CentOS: 推荐使用 MySQL 5.7。虽然 8.0 性能更好,但 8.0 默认启用 InnoDB 缓冲池更大,且多线程架构对单核 CPU 调度开销略高。5.7 在低配下更稳定。
- Ubuntu: 推荐使用 MySQL 5.7 或 MariaDB 10.3+。MariaDB 在低资源环境下通常比 MySQL 稍显轻量。
强烈建议:如果业务允许,优先考虑 SQLite 或 MongoDB (带 WiredTiger 且限制缓存),或者直接使用云厂商提供的 RDS 基础版(哪怕是最便宜的)。本地部署 1G 跑 MySQL 属于“硬扛”。
三、 my.cnf 极致优化配置(核心)
这是成败的关键。以下配置适用于 InnoDB 引擎,目标是让 MySQL 占用内存控制在 300-400MB 以内。
1. Ubuntu (/etc/mysql/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf)
2. CentOS (/etc/my.cnf)
将 [mysqld] 部分修改为以下内容:
[mysqld]
# --- 基础设置 ---
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
port=3306
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
# --- 语言与字符集 ---
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
# --- 关键内存优化 (针对 1G 内存) ---
# InnoDB 缓冲池大小:设置为物理内存的 25%-30%。1G 机器设为 256M 或 384M。
# 切勿超过 400M,否则极易 OOM。
innodb_buffer_pool_size = 256M
# 日志文件大小:减小以减少 I/O 压力,但需确保事务能正常回滚
innodb_log_file_size = 64M
innodb_log_files_in_group = 2
# 追加缓冲区:用于排序和连接
sort_buffer_size = 64K
read_buffer_size = 64K
read_rnd_buffer_size = 64K
join_buffer_size = 64K
# 线程相关:单核服务器,线程数不宜过多
thread_cache_size = 8
table_open_cache = 400
max_connections = 50 # 限制最大连接数,防止并发过高撑爆内存
# --- 其他优化 ---
# 禁用 DNS 解析,加快连接速度
skip-name-resolve
# 关闭不必要的功能
performance_schema = OFF
log_bin_trust_function_creators = 1
# 查询缓存:MySQL 5.7 中 query_cache_type 已废弃,8.0 移除。
# 如果是 5.7,可以开启,但在高并发下可能成为瓶颈。1G 机器建议关闭以节省锁竞争开销。
query_cache_type = 0
query_cache_size = 0
# 慢查询日志:用于排查问题,但要注意磁盘 I/O
slow_query_log = 1
long_query_time = 2
slow_query_log_file = /var/log/mysql/slow.log
验证配置是否生效
重启 MySQL 后,登录数据库执行:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'max_connections';
四、 数据库设计层面的避坑指南
在 1G 机器上,SQL 写法不当会直接导致 CPU 100% 或内存溢出。
- 避免大字段:尽量不要在表中存储大量
TEXT或BLOB数据。如果必须存,考虑存入 OSS/S3 对象存储,数据库中只存 URL。 - 索引优化:
- 每个表必须有主键。
- 避免全表扫描。
SELECT *是大忌,明确指定需要的列。 - 对于小表(数据量 < 1000 行),可以考虑不使用索引,因为 B+ 树遍历的开销可能大于顺序扫描。
- 分库分表思维:
- 如果单表数据超过 500 万行,1G 服务器的 MySQL 会非常吃力。建议在应用层做读写分离或垂直拆分。
- 定期清理 Binlog:
- 在
my.cnf中添加:expire_logs_days = 7 max_binlog_size = 100M - 防止 binlog 占满磁盘空间,导致 MySQL 无法写入而挂起。
- 在
五、 替代方案与更高阶建议
如果上述配置调整后,MySQL 依然频繁卡顿或重启,说明硬件瓶颈已到极限。此时应考虑以下方案:
1. 使用 MariaDB 替代 MySQL
MariaDB 是 MySQL 的一个分支,由原 MySQL 开发者维护,通常在相同配置下性能略优,且对低内存支持更好。
# Ubuntu
sudo apt install mariadb-server
# CentOS
sudo yum install mariadb-server
然后同样应用上述 my.cnf 中的内存优化参数。
2. 使用 SQLite(轻量级场景首选)
如果你的应用是单用户或少量并发,且不需要复杂的权限管理和远程连接,SQLite 是 1G 服务器的王者。它没有服务端进程,所有操作都在本地文件系统中完成,几乎无额外内存开销。
# Python 示例
import sqlite3
conn = sqlite3.connect('app.db')
3. 云厂商的“神技”:云数据库 RDS
国内云厂商(阿里云、腾讯云)的 RDS 基础版(如 1核2G 起步)往往有促销活动,价格并不比你自己买 1核1G 服务器 + 运维成本高多少。
- 优势:自动备份、高可用、专业调优、无需担心 OOM。
- 建议:如果预算允许,升级到 2G 内存的云服务器,或者直接使用云数据库 RDS,体验会有质的飞跃。
4. Docker 容器化部署(可选)
使用 Docker 可以隔离环境,但不会减少资源消耗。反而需要预留 Docker Daemon 的内存。如果非要用 Docker,请限制容器资源:
docker run -d --name mysql
--memory="512m"
--cpus="1.0"
-v /path/to/my.cnf:/etc/mysql/conf.d/custom.cnf
-e MYSQL_ROOT_PASSWORD=yourpassword
mysql:5.7
并在 custom.cnf 中再次强调 innodb_buffer_pool_size=256M。
六、 监控与维护
-
监控内存使用:
top -o %MEM free -h关注
buff/cache和available内存。如果available长期低于 100MB,说明系统已经严重依赖 Swap,性能会大幅下降。 -
定期重启 MySQL:
在极端低配下,MySQL 长时间运行可能出现内存碎片。每周凌晨重启一次 MySQL 服务是一个简单有效的“偏方”:systemctl restart mysqld -
日志轮转:
确保/var/log/mysql/error.log不会无限增长。配置 logrotate 或手动删除旧日志。
总结
在 1核1G 服务器上运行 MySQL,最佳实践 = 开启 Swap + 限制 InnoDB Buffer Pool 至 256M + 限制 Max Connections + 精简 SQL 查询。
请记住,这不是一个生产级的高可用方案,而是一个低成本试错或轻量级个人项目的解决方案。一旦业务增长,请立即迁移至更高配置服务器或云数据库。
云技术博客