报错码是排查起点
MySQL 报出的 ERROR 1064、1054、1213 等号码是服务端错误码,含义固定,可以直接当排查索引使用。同一个错误码在 5.7 与 8.0 上含义基本不变,但报错文案与默认行为有差异。定位顺序是先翻译错误码,再判断该改 SQL、改表结构还是查并发。
基本信息
| 适用 | MySQL 5.7 / 8.0,MariaDB 错误码大体兼容 |
|---|---|
| 号码来源 | 客户端输出与服务端 error log 中的号码一致 |
| 辅助手段 | SHOW WARNINGS / sys.innodb_lock_waits / perror |
| 注意 | SHOW WARNINGS 只反映紧邻的上一条语句 |
常见错误码对照
| 错误码 | 报错文本 | 含义与排查方向 |
|---|---|---|
| 1064 | You have an error in your SQL syntax | 语法错误:保留字当列名、引号不配对、缺逗号;行号是语句内偏移 |
| 1054 | Unknown column in field list | 列名拼错、表别名前缀漏写、视图引用了已删除的列 |
| 1146 | Table doesn't exist | 库名表名大小写、连接未选默认库、DDL 未同步到目标实例 |
| 1062 | Duplicate entry for key | 唯一键或主键冲突,报错直接给出键名与重复值 |
| 1213 | Deadlock found | 死锁被回滚,需查死锁快照并统一加锁顺序 |
| 1205 | Lock wait timeout exceeded | 有长事务持锁,用 sys.innodb_lock_waits 找阻塞线程 |
| 1114 | The table is full | 内存临时表超 tmp_table_size 转磁盘后写满 tmpdir,或磁盘满 |
| 1406 | Data too long for column | 严格模式下超长写入被拒,改列宽或修数据 |
定位锁等待与死锁
定位锁等待与死锁
SELECT * FROM sys.innodb_lock_waits\G # 谁在等谁:waiting_pid 与 blocking_pid
SELECT * FROM information_schema.innodb_trx\G # 活跃事务、开始时间、持锁行数
SHOW ENGINE INNODB STATUS\G # 看 LATEST DETECTED DEADLOCK 段现场
SHOW WARNINGS; # 上一条语句的告警明细
SELECT @@lower_case_table_names; # 迁移后 1146 高发时先查大小写策略典型使用场景
- 上线前用错误码清单核对 DDL 与索引变更,避免低级语法问题进生产
- 死锁告警后按 1213 回溯两个事务的加锁顺序,再统一访问顺序
- 跨平台迁移后批量出现 1146,核实大小写策略与表名写法
- 接口偶发 1205,先定位长事务再决定是否调整锁等待超时
- 批量导入报 1406,检查 sql_mode 严格程度与列定义长度
自查手段怎么读
| 手段 | 关键输出 | 判断依据 |
|---|---|---|
| SHOW WARNINGS | 警告码与文本 | 出现 1265、1366 说明写入被截断或隐式转换 |
| sys.innodb_lock_waits | wait_age、waiting_pid、blocking_pid | wait_age 持续增长说明阻塞者是长事务 |
| information_schema.innodb_trx | trx_started、trx_rows_locked | 事务存活数分钟且持大量行锁,优先评估 kill |
| SHOW ENGINE INNODB STATUS | TRANSACTIONS 与死锁段 | 死锁只保留最近一次现场,需配合日志留存 |
报错里的行号是语句内偏移而不是文件行号,多语句脚本要先按批切分再定位;SHOW WARNINGS 执行下一条语句就会被覆盖。
1213 表示事务已被回滚而不是语句执行失败,应用层必须捕获并重试,重试前加短退避,否则并发高峰会持续撞同一把锁。