模拟一个长事务或者未提交事务

场景1:MDL 锁 / DDL / TRUNCATE 冲突
mysqldump 报错无法获取表锁(--single-transaction可能成功)



场景2:备份期间执行 DDL
--single-transaction 只能保证 InnoDB 数据一致性快照,但不能完全避免 DDL 干扰。备份期间如果对表做 ALTER TABLE、TRUNCATE、DROP,仍可能导致备份失败或数据不一致。
一个大表(可能是 50G)由于磁盘 IO 慢正在备份,备份期间做了 DDL。
mysqldump 报错表结构改变(备份期间表做了 DDL)。

通过 binlog 挖掘可以发现 DDL,可能是截断表或者添加字段。

场景3:网络与通信超时
mysqldump 是客户端工具,数据从 MySQL 服务端流到客户端,再写入本地磁盘或管道。如果写入慢、网络抖动、管道阻塞,服务端会认为客户端接收太慢,主动断开连接。
常见参数:
- net_write_timeout
- net_read_timeout
- wait_timeout
- interactive_timeout
- max_allowed_packet
特别是通过 | gzip 写 NFS、远程网络备份、磁盘 IO 慢时,更容易触发 Lost connection。
场景4:客户端内存或 OOM
不加 --quick 时,mysqldump 可能把整张表结果集缓存在客户端内存里。大表、含 BLOB/TEXT 字段时,客户端内存可能暴涨,甚至被系统 OOM Killer 杀掉。
建议 InnoDB 备份至少带上:
--single-transaction --quick --lock-tables=false
场景5:磁盘、/tmp 或 inode 不足
备份输出路径空间不够、/tmp 写满、inode 耗尽,都会导致备份中途失败。
如果用了管道压缩,还要确认压缩进程没有卡住,否则 TCP 窗口堵死后 MySQL 也会断开连接。
场景6:权限不足
备份用户如果缺少必要权限,也会失败,例如:
- SELECT
- LOCK TABLES
- SHOW VIEW
- PROCESS
- RELOAD
- EVENT
- TRIGGER
常见报错:
- Access denied
- SHOW VIEW 失败
- FLUSH TABLES 失败
场景7:视图、触发器、存储过程异常
如果库里有视图引用了不存在的表或列,或者定义者用户不存在,mysqldump 可能中止。
可以用 --force 继续导出,但要注意它只是忽略错误继续跑,不代表数据完全一致。
场景8:表损坏或 InnoDB 表空间异常
表损坏、.ibd 文件异常、表空间 ID 不匹配时,mysqldump 可能在某张表处中断。
可以先用:
CHECK TABLE orders_db.orders;
SHOW CREATE TABLE orders_db.orders;
SELECT COUNT(*) FROM orders_db.orders;
确认表是否可正常访问。
推荐排查顺序
# 1. 看 MySQL 错误日志
tail -n 300 /var/log/mysql/error.log | grep -i "aborted\|timeout\|metadata lock"
2. 看是否有 MDL 等待
SHOW FULL PROCESSLIST;
SELECT * FROM performance_schema.metadata_locks
WHERE OBJECT_SCHEMA = 'orders_db' AND OBJECT_NAME = 'orders';
3. 看是否有长事务
SELECT * FROM information_schema.INNODB_TRX;
4. 看超时和包大小
SHOW VARIABLES LIKE 'net_write_timeout';
SHOW VARIABLES LIKE 'net_read_timeout';
SHOW VARIABLES LIKE 'max_allowed_packet';
SHOW VARIABLES LIKE 'lock_wait_timeout';
5. 看磁盘空间
df -h /backup
df -h /tmp
df -i /tmp
最稳妥的改法
对于 DDL 场景,优先做三件事:
- 错峰:备份不要和 TRUNCATE、ALTER TABLE 重叠。
- 加参数:--single-transaction --quick --lock-tables=false --max_allowed_packet=256M --net-read-timeout=300 --net-write-timeout=300 --lock-wait-timeout=60。
- 加监控:备份脚本里检查退出码和文件大小,失败就告警,不要只依赖 cron。