mysqldump 高并发下易锁表,因默认执行 flush tables with read lock,即使 –single-transaction 也仅对 innodb 有效且依赖 repeatable read 隔离级;遇 myisam、长事务或 statement 格式 binlog 会退化为全局读锁,导致写阻塞。

mysqldump 在高并发下为什么容易锁表
默认情况下 mysqldump 执行 FLUSH TABLES WITH READ LOCK,会阻塞所有写入,哪怕加了 --single-transaction,也只对 InnoDB 有效,且要求事务隔离级别为 REPEATABLE READ;一旦遇到混合引擎(比如 MyISAM 表)、长事务未提交、或开启了 binlog_format = STATEMENT,就可能退化成全局读锁。
常见现象:SHOW PROCESSLIST 中大量线程卡在 Waiting for table flush,应用写请求超时。
- 务必确认库中无 MyISAM 表:
select TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db' AND ENGINE = 'MyISAM'; - 备份前检查长事务:
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5; - 避免在业务高峰执行,或搭配
--skip-lock-tables(仅适用于全 InnoDB +--single-transaction)
Percona XtraBackup 是什么,为什么它更适合高并发
innobackupex 已被弃用,现在统一用 xtrabackup(v8.0+ 支持 MySQL 8.0,需匹配版本)。它基于 InnoDB 的崩溃恢复机制,拷贝数据文件的同时记录 redo log 偏移,不锁表、不阻塞 DML,备份过程对线上影响极小。
但注意:它只支持 InnoDB 和 XtraDB,不备份 MyISAM、CSV、MEMORY 等非事务表(如有,需额外用 mysqldump --no-create-info 单独导出)。
- 基础全量备份命令:
xtrabackup --backup --target-dir=/backup/full_$(date +%F) - 备份后必须
--prepare才能恢复:xtrabackup --prepare --target-dir=/backup/full_2024-06-01 - 若启用了加密或压缩,
--encrypt/--compress会显著增加 CPU 消耗,建议在从库或低负载节点做
如何用 binlog 做增量备份并保障一致性
单纯全量备份无法满足 RPO binlog 文件名和 position(见 xtrabackup_binlog_info),后续可用 mysqlbinlog 截取增量日志。
关键点在于:增量备份不能“追着主库实时拉”,而应定期(如每 15 分钟)保存一次 SHOW MASTER STATUS,再结合 FLUSH BINARY LOGS 控制单个 binlog 文件大小,避免单文件过大导致解析慢或传输失败。
- 获取上一次备份的位点:
cat /backup/full_2024-06-01/xtrabackup_binlog_info→ 输出类似mysql-bin.000012 1987345 - 拉取增量:
mysqlbinlog --start-position=1987345 mysql-bin.000012 > incr_20240601_1500.sql - 恢复时先
--prepare全量,再按顺序重放所有增量 SQL(注意跳过SET @@session.SQL_LOG_BIN=0这类语句,否则可能污染备份机 binlog)
备份文件校验与恢复演练常被忽略的细节
很多团队备份脚本跑通就认为万事大吉,但没验证过 tar -tzf 是否真包含 ibdata1、是否权限可读、是否跨版本兼容(例如 MySQL 5.7 备份不能直接用于 8.0 --prepare),更没人定期跑恢复测试。
最轻量的校验方式:用 xtrabackup --check-privileges 验证权限,再用 --dry-run(v8.0.30+)模拟 prepare 流程,不真正解压也不修改磁盘。