出现的问题是 mysql 服务跑不起来,检查日志 /var/log/mysqld.log 发现 InnoDB 创建 buffer pool 失败,原因是内存不足。

[Warning] [MY-012681] [InnoDB] page_aligned_alloc mmap(137236480 bytes) failed; errno 12
[ERROR] [MY-012956] [InnoDB] Cannot allocate memory for the buffer pool

使用 free -m 命令查看内存情况

[root@vultr ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:            486         106         260          32         119         334
Swap:             0           0           0

Vultr 服务器只有 512M 内存,基本上被榨干了。。不过竟然没有 swap。

于是:

dd if=/dev/zero of=/swapfile bs=1M count=1024
mkswap /swapfile
swapon /swapfile

其中:

  1. dd if=/dev/zero of=/swapfile bs=1M count=1024

    • dd 是一个用于转换和复制文件的工具。

    • if=/dev/zero 指定输入文件为 /dev/zero,这是一个特殊的设备文件,它会提供无限的零字节流。当dd从这个设备读取时,它会生成连续的零值数据。

    • of=/swapfile 指定输出文件为 /swapfile,这是要创建的目标文件,位于根目录下。

    • bs=1M 表示每次读写的块大小为1兆字节(1MB)。

    • count=1024 表示要读写的块数量,所以这里将写入1024个1MB的块,总共就是1024MB,也就是1GB的数据。

  2. mkswap /swapfile

    • mkswap 是用来设置文件系统中的一个分区或者文件作为交换空间的命令。
    • 当执行 mkswap /swapfile 时,系统会把刚刚创建的 /swapfile 文件格式化为Linux可以识别和使用的交换空间格式。
  3. swapon /swapfile

    • swapon 命令则是用来激活交换空间的。
    • 在执行 swapon /swapfile 之后,Linux内核会将 /swapfile 加入到可用的交换空间列表中,这样在物理内存不足时,操作系统就可以开始使用这个文件作为虚拟内存的一部分。

总的来说就是手动创建并启用一块1GB大小的交换空间,以缓解系统内存压力。

最后添加代码/swapfile swap swap defaults 0 0/etc/fstab文件里面。作用是在系统启动时自动挂载和启用我们刚创建的swap文件。具体来说:

  • /swapfile:指定swap文件的位置,即系统将在启动时尝试激活位于根目录下的名为swapfile的文件作为交换分区使用。
  • 第一个swap:标识这个条目是要被格式化和使用的交换空间。
  • 第二个swap:进一步确认类型为交换空间。
  • defaults:一组默认的挂载选项,通常包括rw(可读写)、relatime(更新文件访问时间的方式)、以及可能的其它默认行为,具体取决于系统配置。对于swap文件,这里的选项主要意味着按照标准方式启用swap。
  • 0:dump备份工具的优先级,对于swap空间通常是不需要备份的,因此设置为0,表示不进行备份。
  • 第二个0:在启动时检查磁盘的顺序,对于swap分区也通常设置为0,表示无需在系统启动时进行fsck检查。

这样一来,每次系统启动时都会自动地将/swapfile当作交换空间来使用,从而确保系统在物理内存不足时有足够的虚拟内存支持运行进程。

再次运行 free -m:

[root@vultr ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:            486         399           7          16          80          58
Swap:          1023          63         960

可以看到,swap 用起来了。

再次运行 mysqld,也跑起来了。