游客发表
上周帮一个做外贸的网站朋友恢复网站,数据库被勒索软件加密了,备份备份文件倒是数据存在,但打开一看——三个月前的网站。他当时觉得每周备份太麻烦,备份设了个自动任务,数据结果脚本跑失败了自己不知道,网站白白丢了九十天的备份订单数据。这事让我意识到,数据很多人对“网站备份数据库”的网站理解还停留在“有个备份文件就行”的阶段。
数据库备份的备份核心不是“备份”这个动作,而是数据“可恢复性”。你存了一堆.sql文件在服务器上,网站跟没备份区别不大。备份服务器硬盘坏了,数据备份文件跟着一起没。更常见的情况是,备份文件在,但版本对不上——比如你用的是MySQL 8.0,备份文件却是5.7导出的,恢复时字符集报错,时间戳字段全乱。我见过最离谱的案例,有人用phpMyAdmin手动导出,选了“快速”模式,结果外键约束全丢了,恢复后数据关系支离破碎。
真正靠谱的做法是把备份文件挪到另一台机器,或者对象存储里。阿里云OSS、腾讯云COS、甚至自己的另一台VPS,都比放在同一块硬盘上强。我自己的习惯是每天凌晨三点用mysqldump导出一份压缩包,通过rclone传到Backblaze B2,保留最近30天。成本一个月不到两块钱,换的是睡得着觉。
备份频率取决于数据变化速度。一个企业官网,每天新增几条留言,每周全量备份一次足够。但如果是电商订单库,每小时都有交易写入,就得考虑增量备份或者binlog。MySQL的binlog是个好东西,配合全量备份可以做时间点恢复。不过binlog本身也会占空间,得设个过期策略,比如保留7天。我见过有人binlog开了半年没清理,磁盘爆了,数据库直接挂掉。
说到具体操作,mysqldump是最常用的工具,但有几个坑得避开。默认它会把整个表锁住,线上业务会卡顿。加--single-transaction参数可以避免锁表,前提是表引擎是InnoDB。还有--routines和--triggers,不加的话存储过程和触发器不会备份,恢复后业务逻辑直接报错。字符集也要指定,--default-character-set=utf8mb4,不然emoji表情存进去变成问号。
恢复演练比备份本身更重要。我每季度会挑一个备份文件,在本地Docker里跑一遍完整恢复流程。有次发现备份文件里少了一张表,原因是备份脚本里写死了数据库名,后来加了个新库没更新脚本。这种问题不演练根本发现不了。恢复时间也得心里有数——一个2GB的数据库,导入可能要十几分钟,业务中断的窗口期得提前规划。
小团队没专职运维的话,可以考虑用现成工具。宝塔面板自带数据库备份功能,能定时任务加云存储,够用。但别完全依赖面板,我遇到过面板升级后备份任务失效的情况。最好还是自己写个shell脚本,加个失败告警,比如备份文件大小小于预期就发邮件。脚本不用复杂,十几行就够,关键是可靠。
最后说个反直觉的点:备份文件不是越多越好。有人保留了两年的每日备份,几百个文件,真出问题时根本不知道恢复哪个。不如保留最近7天每日、最近4周每周、最近12个月每月,这样既有细粒度又有长期归档。清理策略写在脚本里,自动删旧文件,省得手动整理。
数据库备份这事,说到底是跟概率打交道。你永远不知道硬盘什么时候坏、手什么时候抖、勒索软件什么时候来。能做的就是把恢复路径铺好,然后定期走一遍。别等出事了才翻备份文件,那时候每分每秒都是钱。
友情链接