应使用 --defaults-file 指定严格权限(chmod 600)的配置文件存凭据,subprocess 调用需 shell=false、列表传参、分块流式处理、设置超时及字符集参数,避免明文密码和内存溢出。

mysqldump 命令拼接不加 --defaults-file 就容易权限报错
直接用 subprocess.run() 调 mysqldump,如果账号密码写在命令行里(比如 -u root -p123456),MySQL 8.0+ 会直接拒绝,报 Access denied for user 'root'@'localhost' —— 不是因为密码错,而是因为 MySQL 默认禁用了明文传参。更安全也更稳的做法是把凭据塞进配置文件,再用 --defaults-file 指定它。
实操建议:
- 新建一个只读、仅属主可读的配置文件,比如
/home/backup/.my.cnf - 内容必须严格按格式(开头空行不能少):
[client] user = backup_user password = your_strong_password host = localhost
- 执行前务必
chmod 600 /home/backup/.my.cnf,否则mysqldump会直接忽略该文件并报错 - 命令中用
--defaults-file=/home/backup/.my.cnf,不要加空格,路径必须绝对
subprocess.run() 必须设 shell=False 并传列表参数
很多人图省事写成 subprocess.run("mysqldump --defaults-file=... > backup.sql", shell=True),这看似简单,实则埋雷:重定向 > 在 shell=False 下无效;而开 shell=True 又会让密码可能泄露到进程列表(ps aux 可见)。正确姿势是让 Python 自己处理输出流。
实操建议:
- 把命令拆成
list:例如["mysqldump", "--defaults-file=/home/backup/.my.cnf", "mydb"] -
stdout接open(..., "wb")文件对象,别用字符串重定向 - 加
check=True,出错时直接抛CalledProcessError,方便捕获 - 别漏
encoding=None(或显式设text=False),因为mysqldump输出的是二进制 dump,含原始字节
备份大库时没设超时和管道缓冲,脚本卡死或 OOM
导出几十 GB 的库时,subprocess.run() 默认会把所有输出先缓存在内存里,直到命令结束才写文件——这会导致内存爆满,或者因等待太久被系统 kill。另外,如果 MySQL 连接卡住(比如锁表),脚本也会无限挂起。
实操建议:
- 用
subprocess.Popen替代run,边读边写,避免内存堆积 - 给
mysqldump加--single-transaction(InnoDB)或--lock-tables=false(谨慎评估),减少锁等待 - 通过
timeout=3600控制最长执行时间,避免半夜卡住不退出 - 用
stderr=subprocess.PIPE捕获错误输出,mysqldump的警告(如Warning: Skipping the data of table mysql.proc)其实常被忽略,但真正失败时stderr里才有关键线索
gzip 压缩必须用子进程链式调用,别在 Python 里读全量再压缩
有人习惯用 subprocess.run(["mysqldump", ...], stdout=subprocess.PIPE) 拿到 bytes 再喂给 gzip.compress(),这等于把整个 dump 加载进内存两次(一次读,一次压),10GB 库直接炸掉。真正的生产做法是用管道把两个进程串起来,数据流式经过,内存占用恒定。
实操建议:
- 启动
mysqldump进程,stdout=subprocess.PIPE - 再启动
gzip进程,stdin=subprocess.PIPE - 用
dump_proc.stdout.read(8192)分块读,gzip_proc.stdin.write(chunk)分块写 - 或者更简单:用
shlex.split()构造["mysqldump", ...] | gzip > backup.sql.gz"然后shell=True—— 仅当确认环境可控、无用户输入参与时可用
最常被跳过的其实是 .my.cnf 的文件权限和 mysqldump 的字符集参数。比如没加 --default-character-set=utf8mb4,遇到 emoji 就变成问号,而这个错误在 restore 时才暴露,已经晚了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











