可行但需严格隔离执行环境:每个备份任务须独占popen实例、独立文件句柄、显式utf8mb4编码;并发数≤4;启用--single-transaction保障单库一致性;子任务级异常捕获并记录stderr。

直接调用 mysqldump 并发备份多个数据库是可行的,但默认行为极易因连接冲突、锁表或输出重定向竞争导致部分库备份失败或文件损坏——关键不在“能不能并发”,而在“怎么隔离执行环境”。
避免 mysqldump 进程间 stdout 冲突
多个 mysqldump 进程若共用一个 subprocess.run(..., stdout=f) 或管道链,会因文件描述符争用、缓冲区覆盖导致 SQL 文件内容错乱(比如 A 库的 CREATE TABLE 被 B 库的 INSERT 截断)。这不是概率问题,是确定性风险。
- 每个备份任务必须独占一个
subprocess.Popen实例,并显式指定stdout为独立打开的文件对象(open(..., 'w', encoding='utf8')) - 禁止使用
shell=True拼接重定向符号(如"mysqldump ... > file.sql"),这会让 shell 解析器介入,失去对 I/O 的精确控制 - 必须设置
encoding='utf8'(或utf8mb4),否则中文库名、表名、注释可能写入乱码,恢复时报错ERROR 1064
并发控制与资源隔离
盲目开 10 个进程备份 10 个库,MySQL 可能因 max_connections 耗尽拒绝新连接,或触发 wait_timeout 中断 dump 流程。并发数不是越多越好。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 并发数建议设为
min(4, len(db_list)):4 是多数 MySQL 默认max_connections=151下的安全余量 - 每个子进程需独立连接参数,不能共享同一字典对象(避免多线程/进程修改引发竞态)
- 使用
concurrent.futures.ThreadPoolExecutor(非ProcessPoolExecutor)即可:I/O 密集型任务,线程足够,且避免进程间重复加载 pymysql/mysqldump 环境 - 为每个任务加超时控制:
future.result(timeout=600)(10 分钟),防止大库卡死整个备份流程
--single-transaction 必须按库单独启用
--single-transaction 只对单个 mysqldump 进程生效,它依赖事务快照。跨库并发时,每个库的快照时间点不同,无法保证“所有库在同一时刻一致”。但这不意味着该参数没用——它仍能确保单库内 InnoDB 表不锁表、数据逻辑自洽。
- 必须为每个库的命令显式添加
--single-transaction,尤其当库中含大量写入业务表时 - 若某库含 MyISAM 表,
--single-transaction无效,此时应搭配--lock-all-tables(但会全局锁,慎用)或改用--lock-tables=false+ 接受非一致性风险 - 务必加上
--default-character-set=utf8mb4,否则导出的中文字段在恢复时可能被截断或报错ERROR 1366
错误捕获必须落到每个子任务粒度
主流程用 try/except 包裹整个 executor.map() 没用——子任务异常会被吞掉,你只会看到“某几个库没生成文件”,却不知原因。
- 每个备份函数内部必须有完整
try/except,捕获subprocess.CalledProcessError和OSError(如路径无写权限、磁盘满) - 将错误信息写入统一日志文件,格式包含:库名、命令完整字符串、
stderr输出、退出码 - 返回值设计为
(db_name, success: bool, error_msg: str)元组,主线程汇总后打印失败列表,不中断其他库备份 - 特别检查
mysqldump是否在 PATH 中:shutil.which('mysqldump'),Windows 下常见缺失此检查导致静默失败
最易被忽略的是:并发备份时,mysqldump 进程的 stderr 输出若未被捕获并写入日志,错误就彻底消失。哪怕只漏掉一条 Access denied for user,整个备份就不可信。别依赖“文件存在即成功”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










