mysql增量备份需依赖binlog position或updated_at字段,生产环境推荐mysqldump配合--master-data=2记录binlog位点,后续通过rsync同步新binlog;密码须用--defaults-extra-file传入,subprocess.run需设timeout和stderr捕获,rsync同步应使用--delete-after与显式ssh密钥并原子更新position文件。

直接上结论:用 subprocess 调用 mysqldump + rsync 是最轻量、可控性最强的方案,比依赖第三方 Python 库(如 mysql-connector 自己拼 SQL 做增量)更可靠,也比全量备份+时间戳命名更节省空间和带宽。
怎么识别并导出 MySQL 的增量数据?
MySQL 本身不提供“上次备份后新增/修改的行”这种接口,所谓“增量备份”在脚本层面实际靠的是 binlog + position 或时间戳字段。生产环境强烈推荐 binlog 方式:
-
mysqldump --single-transaction --skip-triggers --master-data=2可在导出瞬间记录 binlog 文件名和位置,后续备份只需从该 position 开始拉取新 binlog - 若表有
updated_at字段且业务保证更新必改该字段,可用--where="updated_at > '2024-06-01 00:00:00'",但注意时区、索引缺失会导致慢查询甚至锁表 - 不要用
SELECT ... INTO OUTFILE替代mysqldump:它不包含建表语句、权限信息,且受secure_file_priv限制
如何用 Python 安全调用 mysqldump 并捕获失败?
Python 不该自己实现 dump 逻辑,而是做流程控制和错误兜底。关键点在于环境隔离和输出处理:
- 用
subprocess.run()而非os.system():前者能精确捕获returncode和stderr - 密码必须通过
--defaults-extra-file传入配置文件(如/etc/mysql/backup.cnf),禁止出现在命令行或环境变量中,防止被ps aux窃取 - 务必设置
timeout=300,避免大表卡死进程;捕获到CalledProcessError后立即发告警(比如写入本地/var/log/backup.err) - 示例片段:
result = subprocess.run([ "mysqldump", "--defaults-extra-file=/etc/mysql/backup.cnf", "--single-transaction", "mydb" ], stdout=open(backup_path, "wb"), stderr=subprocess.PIPE, timeout=300)
rsync 同步时为什么总漏文件或报 permission denied?
rsync 不是“复制完就完事”,权限、路径、SSH 配置错一个就会静默失败或同步不全:
- 目标机器的备份目录必须由 rsync 用户可写,且
rsync -avz中的-a会保留权限,如果源文件属主是mysql:mysql,目标机没这个用户组就会报错 —— 改用-rltDvz显式控制保留项 - 使用
--delete-after而非--delete:先传新文件再删旧文件,避免网络中断导致目标端清空 - SSH 必须配置免密登录,且用
-e "ssh -i /root/.ssh/backup_key"指定私钥,不能依赖~/.ssh/config(crontab 下 $HOME 可能不是预期路径) - 加
--dry-run先跑一次看实际要同步哪些文件,比盲猜靠谱得多
真正难的不是写通整个流程,而是 binlog position 的保存与校验 —— 它必须原子写入本地文件(比如用 atomicwrites 或重命名方式),且每次 rsync 成功后再更新,否则断电或网络闪断会导致下一轮从错误位置开始拉 binlog,丢数据。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











