前言
在动笔写下这篇文章的时候,已经接近凌晨三点
1 | postgres=# select now(); |
笔者最近睡得晚,基本都是 12.30 以后才入睡,今天凌晨 1 点多的时候,刚进入梦乡没多久,便被一通急促的微信语音给吵醒:
强忍睡意和焦躁的情绪,我看了一下这位读者发来的信息 —— 误删了表,并且是 TRUNCATE,经过了解,这位读者原本想在订阅端执行 TRUNCATE 操作,但是粗心,在发布端执行了此操作。在 PDU 工具正式诞生以前,对于 TRUNCATE/DROP 等操作,基本只能求助于备份恢复了,因此我也是第一时间告诉这位读者这个手段,但是可惜的是,备份只有上个月 21 号的,并且此期间的 WAL 也不是连续的,缺失了一部分,因此 PITR 的方式也行不通。
所以,只能寄希望于 PDU 了,但是可惜的是,在初始化的过程中,遇到了两个问题:
- 第一次执行,提示数据库版本不匹配
- 第二次执行,提示 Segmentation fault
因此,PDU 这条路也行不通了。在经过一小时的腾讯会议之后,我也很遗憾地告诉了这位读者,数据库层面的手段用尽了,至少我这边黔驴技穷了,文件系统层面的恢复也不是笔者所擅长的,但是好在这位读者通过其他手段,找回了上午 10 点以前的数据,业务至少不报错了,只是可能丢失了部分数据,所以只能从应用层面再想想办法了。
为什么我会在腾讯会议结束之后,第一时间写下了这篇文章,实在是感触颇深:
- 执行任何 DDL 之前,尤其是高危操作,比如 DROP/TRUNCATE/DELETE 等,一定要慎之又慎,我现在也能愈发理解,为何之前的运维同事每次做一个细微操作都要反复校验了,生产数据重于一切;PostgreSQL 提供了一切可靠的基础设施,比如事务性 DDL,在做此类操作之前,显式开启一个事务,能挽救很多误操作
- 备份,备份真的很重要,定期校验备份的一致性和可靠性也很重要,原生提供了 pg_verifybackup,第三方备份工具也都有 validate 的功能
- 定期做容灾演练,故障恢复可以极大程度减少此类问题的发生
- walminer/PDU 等恢复工具仅能作为最后的兜底手段,不应该也不能将所有的宝都押注于此,万一出现 BUG 呢?只要是软件,没有任何人能确保他的软件不出问题,届时那真的是叫天天不应,叫地地不灵了;关于 PDU,笔者最近也一直在和原作者积极地沟通,包括后续发展和规划、文档建设等,也衷心希望 PDU 工具能够越来越成熟强大 —— 挽狂澜于既倒,扶大厦之将倾
- 操作之前多问自己几遍:是不是目标表?是不是该在生产上执行?是不是该在这个时间点执行?代码写错可以回滚,文档写错可以重写,但生产数据一旦丢失,可能意味着财务损失、合规风险、甚至业务停摆。我们作为 DBA/管理员,最怕的不是数据库 BUG,而是一次”误操作”。PostgreSQL 同样提供了足够清可靠的基础设施,比如 psqlrc,用于识别当前连的环境、用户名和数据库名等等
最后,很遗憾,没能挽救这一套生产集群,也不知道这件误删的事情会对这位读者带来多大的影响。也希望这件事,能够再一次为我们敲响警钟,生产环境里,没有”撤销键”。技术能力很重要,但在生产环境里,真正决定成败的,往往是一份小心和谨慎。