mysql启动失败报“failed to create shared memory segment”是因内核shmmax值小于innodb_buffer_pool_size所致,需同步调整shmall、信号量参数,并在ubuntu等系统中将配置写入/etc/sysctl.d/下以确保生效。

为什么 MySQL 启动失败报 Failed to create shared memory segment
这是典型的内核共享内存(shm)限制不足导致的。MySQL 5.7+ 默认启用 innodb_use_sys_malloc=OFF 时,会通过系统 V 共享内存(shmget)分配大块缓冲区;若 /proc/sys/kernel/shmmax 小于 innodb_buffer_pool_size,服务直接启动失败,日志里常见 Cannot allocate memory 或 Invalid argument。
-
shmmax必须 ≥innodb_buffer_pool_size(单位字节),例如 Buffer Pool 设为 12G,shmmax至少设为12884901888 - 别只调
shmmax:还要同步检查shmall(总页数),它 =shmmax / PAGE_SIZE(通常 PAGE_SIZE=4096),否则仍可能触发ENOMEM - 临时生效用
sysctl -w kernel.shmmax=12884901888;永久写入/etc/sysctl.conf,但必须运行sysctl -p才加载
信号量(semaphores)不够时 MySQL 报什么错
错误信息通常是 semget: No space left on device 或 Operation not permitted,尤其在高并发连接(如 >1000)或大量临时表操作时触发。Linux 信号量由 semmsl、semmns、semopm、semmni 四个参数控制,MySQL 主要受 semmns(系统总信号量数)和 semmni(信号量集数量)制约。
- 一个 MySQL 连接最多消耗 2 个信号量(用于互斥锁和条件变量),所以
semmns建议 ≥max_connections × 2 × 1.2(留 20% 余量) -
semmni至少为max_connections / 10 + 10,避免信号量集耗尽(ipcs -l可查当前限制) - 别盲目调高
semmsl(单集最大信号量数):MySQL 不需要单集超 250 个,设太大反而浪费内核资源
怎么验证修改后的内核参数已真正生效
不能只看 sysctl -p 是否成功返回,得确认内核实际加载值和 MySQL 运行时是否感知到。最可靠方式是分两步验证:
- 查当前值:
cat /proc/sys/kernel/shmmax和ipcs -l,对比是否与/etc/sysctl.conf一致 - 重启 MySQL 后执行
SELECT @@innodb_buffer_pool_size;,再用ipcs -m查共享内存段大小,应 ≥ 查询结果(注意单位:SQL 返回字节,ipcs -m的bytes列也是字节) - 如果
ipcs -m显示段大小远小于innodb_buffer_pool_size,说明 MySQL 回退到了 mmap 分配模式——此时要检查innodb_use_sys_malloc是否被意外关闭,或shmmax仍不达标
CentOS 7/8 和 Ubuntu 20.04+ 的关键差异点
systemd 会覆盖部分 sysctl 设置,尤其是 Ubuntu 20.04+ 默认启用 kernel.sysrq=1 并禁用部分 shm 参数继承,而 CentOS 7 的 systemd-sysctl 加载顺序更“老实”。这不是发行版 bug,而是 systemd 对内核参数的加载策略不同。
- Ubuntu 系统必须把参数写进
/etc/sysctl.d/99-mysql.conf(而非仅/etc/sysctl.conf),否则systemctl daemon-reload后可能不生效 - CentOS 7 上如果用了
grubby修改内核启动参数(如加systemd.unified_cgroup_hierarchy=0),可能导致sysctl设置被 cgroup v2 覆盖,需额外检查/proc/sys/kernel/shmmax实际值 - 所有系统都建议在修改后运行
sudo systemctl restart systemd-sysctl,比单纯sysctl -p更可靠
共享内存和信号量不是越大越好,过大的 shmmax 会让内核预留更多不可交换内存,影响其他进程;过多信号量则增加内核调度开销。调参前先用 mysqltuner.pl 或 SHOW VARIABLES LIKE 'max_connections' 算出真实需求,再留 15–20% 余量——多出来的那点性能,往往不如一次准确的估算来得实在。











