努力
加油

阿里云服务器未配置数据盘,如何安全地安装和使用MySQL数据库?

这是一个非常经典且务实的问题。很多刚接触阿里云 ECS 的新手,为了省钱或者图省事,只买了一块系统盘(通常 40G-100G),没挂载数据盘,结果 MySQL 一跑起来,日志稍微大点,或者数据稍微多一点,系统盘就满了,导致服务器直接卡死甚至无法 SSH 登录。

在没有独立数据盘的情况下,安全、稳定地安装和使用 MySQL,核心思路只有两个:一是把数据目录迁移到系统盘的剩余空间或指定分区;二是通过配置严格限制磁盘使用上限。

以下是基于生产环境经验的实操方案,按推荐程度排序:

方案一:逻辑卷管理(LVM)——最稳健的“伪”扩展方案

如果你在安装系统时选择了 LVM(大多数云厂商默认镜像都支持),这是在不增加物理磁盘的情况下,未来最容易扩容的方法。即使现在不扩容,先建立好结构也是好习惯。

  1. 确认当前状态

    df -h
    lsblk
    pvs   # 查看物理卷
    vgs   # 查看卷组
    lvs   # 查看逻辑卷
  2. 创建 MySQL 专用逻辑卷(如果尚未创建)
    假设你的系统盘是 /dev/vda,根分区是 /dev/vda2。你可以从根分区划出一部分空间给 MySQL。
    注意:直接从已使用的 LV 中缩小风险极大,建议先在 vgdisplay 中看到有足够的 Free PE(空闲物理扩展块)。如果没有,此路不通,请看方案二。

  3. 修改 MySQL 数据目录指向
    这是关键一步。默认 MySQL 数据在 /var/lib/mysql。你需要将其移动到新的逻辑卷上。

    • 停止 MySQL:systemctl stop mysqld
    • 移动数据:mv /var/lib/mysql /mnt/mysql_data (临时存放)
    • 挂载新逻辑卷到 /var/lib/mysql
    • 修改权限:chown -R mysql:mysql /var/lib/mysql
    • 启动 MySQL:systemctl start mysqld

优点:未来如果想加数据盘,只需将新盘加入 VG 并扩展 LV,无需停机迁移数据。
缺点:对初始磁盘规划有要求,如果系统盘已满,无法操作。


方案二:挂载至系统盘非根分区(/data 或 /opt)——最通用的做法

如果你的系统盘只有一个根分区 /,且已经占用了大部分空间,我们需要找一个“角落”安顿 MySQL。

步骤 1:评估空间

df -h /

确保 / 分区还有至少 10-20GB 的可用空间。MySQL 本身很小,但数据和 Binlog 会迅速膨胀。

步骤 2:创建专用目录并设置权限

不要直接把数据放在 /root 或其他用户目录下。

# 创建目录
mkdir -p /data/mysql

# 赋予 mysql 用户权限
chown -R mysql:mysql /data/mysql
chmod 750 /data/mysql

步骤 3:修改 MySQL 配置文件

编辑 /etc/my.cnf 或 /etc/mysql/my.cnf(取决于发行版,CentOS 通常是 my.cnf,Ubuntu 可能是 mysql.conf.d/mysqld.cnf)。

找到 [mysqld] 段,修改 datadir:

[mysqld]
datadir=/data/mysql
socket=/var/lib/mysql/mysql.sock

注意:如果是 Ubuntu/Debian,可能还需要修改 pid-file 和 tmpdir 的位置,避免写入冲突。

步骤 4:处理 SELinux(仅限 CentOS/RHEL)

如果开启了 SELinux,直接改路径会导致 MySQL 启动失败。

# 查看上下文
ls -Zd /data/mysql
# 如果报错,需要重新标记上下文
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
restorecon -Rv /data/mysql

步骤 5:重启并验证

systemctl restart mysqld
systemctl status mysqld
mysql -u root -p -e "SHOW VARIABLES LIKE 'datadir';"

方案三:关键的安全与稳定性配置(无数据盘场景的核心)

既然没有独立数据盘,防止系统盘被写满导致服务器宕机就是最高优先级。必须做好以下配置:

1. 严格控制 Binlog 过期时间

Binlog 是 MySQL 增长的元凶。默认情况下,Binlog 不清理,直到磁盘爆满。
在 my.cnf 中添加或修改:

# 保留 7 天的 binlog,超过自动删除
expire_logs_days = 7
# 或者更激进一点,保留 3 天
# expire_logs_days = 3

注意:新版 MySQL (8.0+) 推荐使用 binlog_expire_logs_seconds,单位是秒。

2. 限制 InnoDB 缓冲池大小

如果你的服务器内存有限(比如 2G 或 4G),不要把 innodb_buffer_pool_size 设得太大,否则 Swap 交换频繁,IO 性能骤降。

# 设置为物理内存的 50%-70%
innodb_buffer_pool_size = 1G

3. 开启自动清理旧数据策略

对于非核心业务表,设置 max_binlog_size 和合理的 purge 策略。

# 单个 binlog 文件最大 1G,避免单个文件过大
max_binlog_size = 100M

4. 监控告警(必做!)

没有数据盘意味着系统盘和数据盘共用 IO 和空间。一旦磁盘使用率达到 80%,MySQL 可能还能写,但 90% 以上就会开始报错,95% 以上服务中断。

  • 安装 zabbix-agent 或阿里云自带的云监控插件。
  • 设置磁盘使用率 > 80% 时发送短信/邮件告警。

5. 定期备份而非依赖磁盘空间

既然磁盘紧张,就不要指望靠磁盘空间来维持长期运行。

  • 使用 mysqldump 或 XtraBackup 每天凌晨全量/增量备份。
  • 备份文件上传到 OSS(对象存储),而不是留在本地磁盘。
  • 命令示例:
    # 每天凌晨 2 点备份,压缩后传到 OSS(需配置 ossutil)
    0 2 * * * /usr/local/bin/backup.sh >> /var/log/mysql_backup.log 2>&1

常见坑点与避坑指南

  1. 不要使用 tmpfs 作为数据目录
    有人提议把 /var/lib/mysql 挂载到内存文件系统(tmpfs)以提速。这在测试环境可行,但生产环境绝对禁止。重启服务器后数据全部丢失,且内存不足时会导致 OOM Killer 杀死 MySQL 进程。

  2. 不要手动解压安装包覆盖原有目录
    如果之前用过 yum/apt 安装的 MySQL,直接解压二进制包替换会导致库文件版本不一致、权限混乱。务必卸载旧版,再安装新版。

  3. 系统盘 IOPS 瓶颈
    阿里云 ESSD 云盘性能较好,但如果只是基础型云盘,高并发下 IO 延迟会很高。观察 iostat -x 1,如果 %util 持续接近 100%,说明磁盘已达瓶颈。此时除了优化 SQL,唯一解决办法是升级云盘类型或加装数据盘。

  4. 字符集问题
    在新建数据库实例时,务必指定 utf8mb4 字符集,避免后续出现 emoji 表情或特殊符号插入失败的问题。

总结

在无数据盘环境下,“空间隔离 + 自动清理 + 外部备份” 是三大支柱。

  1. 空间隔离:将 datadir 移到 /data/mysql 等非系统核心目录,便于管理和监控。
  2. 自动清理:强制设置 expire_logs_days,防止 Binlog 撑爆磁盘。
  3. 外部备份:数据存在本地都是耍流氓,必须定时备份到 OSS。

如果业务数据量预计会超过 50GB,强烈建议还是花几十块钱买一块最低配的数据盘(如 40G SSD),挂载到 /data,这样运维压力会小得多。毕竟,磁盘成本远低于故障恢复成本。