努力
加油

CentOS或Ubuntu系统下,1核1G服务器安装MySQL的最佳实践是什么?

在 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% 或内存溢出。

  1. 避免大字段:尽量不要在表中存储大量 TEXT 或 BLOB 数据。如果必须存,考虑存入 OSS/S3 对象存储,数据库中只存 URL。
  2. 索引优化:
    • 每个表必须有主键。
    • 避免全表扫描。SELECT * 是大忌,明确指定需要的列。
    • 对于小表(数据量 < 1000 行),可以考虑不使用索引,因为 B+ 树遍历的开销可能大于顺序扫描。
  3. 分库分表思维:
    • 如果单表数据超过 500 万行,1G 服务器的 MySQL 会非常吃力。建议在应用层做读写分离或垂直拆分。
  4. 定期清理 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。


六、 监控与维护

  1. 监控内存使用:

    top -o %MEM
    free -h

    关注 buff/cache 和 available 内存。如果 available 长期低于 100MB,说明系统已经严重依赖 Swap,性能会大幅下降。

  2. 定期重启 MySQL:
    在极端低配下,MySQL 长时间运行可能出现内存碎片。每周凌晨重启一次 MySQL 服务是一个简单有效的“偏方”:

    systemctl restart mysqld
  3. 日志轮转:
    确保 /var/log/mysql/error.log 不会无限增长。配置 logrotate 或手动删除旧日志。

总结

在 1核1G 服务器上运行 MySQL,最佳实践 = 开启 Swap + 限制 InnoDB Buffer Pool 至 256M + 限制 Max Connections + 精简 SQL 查询。

请记住,这不是一个生产级的高可用方案,而是一个低成本试错或轻量级个人项目的解决方案。一旦业务增长,请立即迁移至更高配置服务器或云数据库。