MySQL在长期使用或异常重启后,经常会向错误日志中写入“系统错误(System error)”相关记录。这类问题通常不是普通的SQL执行报错,而是MySQL进程在调用操作系统接口时失败,例如读写文件、申请内存、创建线程等环节出现了底层异常。理解这些错误的来源,是快速恢复服务的关键。

一、什么是MySQL系统错误
在MySQL的错误日志里,我们常看到类似“Can't open file(Errcode: 13 - Permission denied)”或者“Got error 28 from storage engine”的提示。这里的Errcode其实是操作系统返回的错误号,MySQL只是原样透传。系统错误与普通的SQL语法错误不同,它意味着MySQL依赖的底层环境出了问题,而不是你写的SELECT语句有误。
从实现原理看,MySQL的存储引擎(如InnoDB、MyISAM)在刷盘、打开表文件、分配缓冲池时都会调用Linux的open、write、mmap等系统调用。当这些调用返回非0值时,MySQL会把错误码记录到日志中。因此排查系统错误,本质是在排查操作系统与MySQL之间的交互故障。
二、常见系统错误原因与排查
1. 权限不足导致Errcode 13
这是最典型的系统错误之一。当MySQL进程用户(通常是mysql)没有数据目录或表文件的读权限时,就会报Permission denied。很多人在迁移数据目录后用root建了文件,却忘了改属主,重启MySQL立刻报错。
排查时可以先看错误日志定位具体文件路径,再用ls -l确认权限。修复方式是用chown把目录交还mysql用户,并确认父目录有执行权限。示例如下:
# 查看错误日志片段 tail -n 20 /var/log/mysql/error.log # 修改数据目录属主 chown -R mysql:mysql /var/lib/mysql # 确认目录权限至少应为750 chmod 750 /var/lib/mysql
2. 磁盘空间耗尽Errcode 28
当磁盘满时,MySQL写binlog或临时文件会失败,报Errcode 28(No space left on device)。这种错误往往伴随实例假死,因为InnoDB无法完成checkpoint。
此时应优先清理无用日志或扩容磁盘。可以通过df -h快速定位满盘分区,并用perror工具把错误号翻译成人类语言:
# 查看各分区使用率 df -h # 将错误号28翻译为具体含义 perror 28
3. InnoDB文件损坏
如果服务器掉电,ibdata或ib_logfile可能不完整,启动时会报系统错误并提示校验失败。轻量损坏可加innodb_force_recovery启动,但值过大会丢数据。
建议先在配置文件中设置恢复级别,导出数据后重建实例。示例如下:
[mysqld] # 1到6逐级增强,仅用于导出数据 innodb_force_recovery = 4
三、通用排查命令与修复建议
使用perror反查错误
MySQL自带perror命令,能把数字错误码转为文字说明,比盲目搜索高效得多。比如perror 13直接告诉你权限拒绝,避免误判为程序bug。
对于MyISAM表损坏引起的系统级读写异常,可用REPAIR TABLE修复,但InnoDB不应这样处理。日常应开启定期备份,降低单点故障风险。
-- 修复MyISAM表(InnoDB不适用) REPAIR TABLE user_info; -- 查看当前打开文件限制 SHOW VARIABLES LIKE 'open_files_limit';
调整资源限制
Linux默认单进程打开文件数较小,高并发时MySQL容易报EMFILE类系统错误。应在系统层修改limits.conf,并同步调大MySQL的open_files_limit。
| 参数 | 作用 | 建议值 |
|---|---|---|
| open_files_limit | MySQL进程最大文件句柄 | 65535 |
| table_open_cache | 缓存打开表数量 | 4096 |
修改后需重启实例生效。若业务频繁遇系统错误,应结合监控观察句柄与磁盘曲线,而非每次被动救火。
四、总结
MySQL系统错误看似吓人,实质是底层资源或权限的映射。掌握perror、日志定位与权限修复三板斧,多数故障可在十分钟内厘清。生产环境务必做好备份与资源监控,让系统错误从“事故”变成“日常告警”。