高并发下mysqldump是否锁表取决于存储引擎和参数:myisam默认加读锁阻塞写入,innodb启用--single-transaction可不锁表但需repeatable read隔离级别且无长事务。

高并发下直接 mysqldump 会锁表吗
会,但取决于存储引擎和参数。MyISAM 表执行 mysqldump 默认加读锁,写请求会阻塞;InnoDB 表默认开启 --single-transaction(PHP 调用时需显式传入),可保证一致性快照,不锁表——但前提是事务隔离级别为 REPEATABLE READ,且备份期间不能有长事务拖慢快照创建。
- PHP 中调用务必加上
--single-transaction --skip-lock-tables,否则 InnoDB 也可能被锁 - 避免在业务高峰执行,哪怕用了事务快照,大表 dump 仍会加重 I/O 和主从延迟
-
FLUSH TABLES WITH READ LOCK这类显式全局锁绝对不要在 PHP 自动脚本里用,极易卡住线上写入
PHP 脚本调用 mysqldump 的安全写法
用 exec() 或 proc_open() 直接拼接命令风险极高,容易被注入(比如数据库密码含特殊字符或变量未过滤)。正确做法是分离参数、强制指定编码、重定向错误流。
- 用
escapeshellarg()包裹每个外部输入:用户名、密码、库名、输出路径 - 显式指定字符集:
--default-character-set=utf8mb4,避免备份文件乱码 - 通过
proc_open()捕获 stderr,判断是否出现Access denied或Got errno类错误 - 示例关键片段:
cmd = 'mysqldump --single-transaction --skip-lock-tables --default-character-set=utf8mb4 -u ' . escapeshellarg($user) . ' -p' . escapeshellarg($pass) . ' -h ' . escapeshellarg($host) . ' ' . escapeshellarg($db) . ' > ' . escapeshellarg($backupFile)
备份文件过大导致 PHP 超时或内存溢出怎么办
PHP 不适合处理 GB 级 SQL 文件的生成或压缩。mysqldump 本身是独立进程,但若用 shell_exec() 捕获全部输出,会把整个 SQL 塞进内存,必然崩。
- 永远用重定向(
>)写入文件,而不是捕获 stdout - 压缩交给系统命令:追加
| gzip > *.sql.gz,别用 PHP 的gzencode()处理原始输出 - 设置超时:用
set_time_limit(0)前先确认脚本运行用户有足够 CPU/IO 配额,否则只是掩盖问题 - 大库分表备份:用
--ignore-table=db.table1 --ignore-table=db.table2拆成多个小任务异步跑
如何避免备份时主从延迟飙升
备份本身不复制数据,但 mysqldump 的全表扫描会触发大量磁盘 I/O 和 Buffer Pool 冲刷,间接拖慢从库 SQL 线程应用 relay log 的速度,尤其当从库配置弱于主库时。
立即学习“PHP免费学习笔记(深入)”;
- 优先在从库备份(需确保
read_only=OFF且无写入),并加--master-data=2记录位点 - 用
--no-autocommit --skip-extended-insert减少单条 INSERT 长度,降低恢复时锁表时间(但会增大文件体积) - 监控
Seconds_Behind_Master,脚本中加入延迟阈值检查,超 60 秒自动暂停备份 - 真正关键的不是“能不能备”,而是“备完能不能快速恢复”——所以每次备份后应抽样校验
gunzip -t和前 100 行语法











