之前手动备份MySQL总是忘记,数据差点丢失。于是写了一个Python脚本,每天凌晨自动备份并上传到阿里云OSS,同时清理30天前的旧备份。

脚本核心:使用`subprocess`调用`mysqldump`,然后使用`oss2`库上传。设置crontab每天2点执行。

关键代码片段:

			import oss2, subprocess, datetime, os
			bucket = oss2.Bucket(auth, 'oss-cn-hangzhou.aliyuncs.com', 'bucket-name')
			filename = f"backup_{datetime.date.today()}.sql"
			subprocess.run(f"mysqldump -u root -p123456 --all-databases > {filename}", shell=True)
			bucket.put_object_from_file('backup/'+filename, filename)
			

现在已经稳定运行三个月,再也不用担心数据丢失了。

脚本详解:从零到一构建自动备份系统

最初版本非常简单,只有上面几行代码。但运行几天后发现问题:密码明文写在脚本里有安全隐患;如果数据库很大,mysqldump会阻塞脚本;上传失败没有重试机制;OSS旧文件需要手动清理。因此我迭代了三个版本。最终脚本包含以下功能:1)从环境变量读取数据库密码和OSS密钥;2)使用`--single-transaction`和`--quick`参数避免锁表;3)用`subprocess.Popen`实现异步备份,并记录日志;4)上传后校验文件大小,如果小于1KB则重试三次;5)每天备份后列出OSS中30天前的文件并删除。另外,为了节省空间,我增加了gzip压缩,压缩率约80%,一个2GB的数据库压缩后只有400MB。脚本使用Python标准库`logging`记录详细操作,便于排查问题。

配置阿里云OSS:创建Bucket与权限管理

首先登录阿里云控制台,创建一个私有Bucket(例如`my-database-backup`),地域选择离自己最近的节点,存储类型选择低频访问,可以节省成本。然后进入RAM访问控制,创建一个子账号,授予该Bucket的读写权限。最后生成AccessKey ID和Secret。在运行脚本的服务器上,不要硬编码密钥,而是设置环境变量:`export OSS_KEY_ID=xxx` `export OSS_KEY_SECRET=yyy` `export MYSQL_PWD=zzz`。脚本中使用`os.getenv`读取,这样即使脚本泄露,也不会直接暴露密码。安全无小事。

定时任务配置:crontab与日志轮转

在Linux服务器上,使用`crontab -e`添加一行:`0 2 * * * /usr/bin/python3 /opt/backup_mysql.py >> /var/log/backup_mysql.log 2>&1`。注意使用python的绝对路径,并给脚本添加可执行权限。另外,为了防止日志文件过大,我配置了logrotate:新建`/etc/logrotate.d/backup_mysql`,内容为每天轮转、保留7天、压缩旧日志。这样每天凌晨2点,脚本安静地执行备份和上传,第二天早上检查邮箱里的日志摘要即可。如果备份失败,脚本会发送邮件到我的工作邮箱,通过调用本地的sendmail或使用smtp库。有了这套监控,基本可以高枕无忧了。

性能优化与踩坑记录

在实际运行中,我遇到几个坑:第一,`mysqldump`对InnoDB表使用`--single-transaction`会开启一个长事务,如果备份时间超过1小时,可能导致undo表空间膨胀。解决方案是拆分数据库,每次只备份一个库,并且对日志表跳过(因为日志不重要)。第二,上传到OSS时如果网络波动,`put_object_from_file`会抛出异常。我封装了重试装饰器,指数退避,最多三次。第三,压缩时使用`pigz`替代`gzip`,利用多核CPU加快压缩速度。经过这些优化,备份7个库共80GB数据,耗时从2小时降到35分钟,效果显著。

扩展:备份其他数据源与异地容灾

同样的模式可以应用于PostgreSQL(pg_dump)、MongoDB(mongodump)甚至文件目录。我后来增加了对`/etc`和`/home`下重要配置文件的备份,打包成tar.gz后上传到同一个OSS Bucket。另外,为了符合3-2-1备份原则,我配置了OSS生命周期规则,将30天前的备份自动转储到归档存储,同时利用阿里云跨区域复制功能,将备份同步到另一个城市的Bucket。这样即使本地机房发生灾难,数据依然可以从异地恢复。最后提醒一点:恢复数据前一定要先测试!我每三个月会做一次演练,在测试服务器上恢复备份,确保数据可用。自动备份只是手段,能恢复才是目的。

脚本我已经上传到GitHub,欢迎有需要的朋友fork修改。数据库备份这件事,值得每一位开发者重视——毕竟,丢失数据的痛苦,谁都不想体验第二次。