在 6 月 26 日凌晨 12 点左右,我们在做线上数据库的备库时,误将线上数据库分区上的所有文件删除。丢失的数据时间段为 4 月 23 日至 6 月 25 日两个月,在经过 7 天的努力后,恢复了 99% 以上的数据(具体见下文的统计)。
下面把整个事故过程记录下来,令关心本次技术事故的人们知晓。
一. 事故隐患
现在回顾,事故隐患在 4 月 23 日之后就已经存在。
我们线上数据库使用的是 MySQL,在 4 月 23 日之前,我们对线上数据库主节点有三类备份。一是有一个独立的数据库从节点来备份,与线上服务器保持数据的实时同步,需要时可切换作线上使用。二是会定期把整个数据库 dump 成 sql 文件来备份,一天保存一次,备份的来源是数据库从节点。三是主节点开启有 binlog,默认是保存十天的日志,十天内有任何事故可以从日志里完整恢复全部数据。这三个备份分别存放在两台不同的物理机,三个不同的分区上,是当时想到的最安全的方式。
4 月 23 日,我们把数据库主节点迁移到一台新的物理机上,并把版本升级到 5.5。由于版本和配置的问题,原来的从节点并不能直接使用。而一天一次的备份来源是从节点(备份主节点会令网站和手机 app 有 1 小时左右的卡顿),这个备份方式也就停止了更新。只有最后一个 binlog 还在运行。数据库迁移之后应用服务器存在一些性能问题需要投入时间,包括修复 MySQL 5.5 版本和原代码的兼容,以及把应用服务器从 gunicorn 换成 uwsgi,之后又陆续有一些开发任务,以致重新启用备份节点的工作一再拖延。
我们对数据库迁移工作的管理存在失误,是造成事故的根本原因。没有完成数据库备份节点,迁移工作就并没有结束。我们技术团队的所有人对这个事故都负有责任,这个隐患在两个月里都可能被发现,每个人都有可能提出这个工作的高优先级。也都可能提出相应的弥补工作来保证数据安全,比如在启用从节点前延长二进制日志的保存时间等。是我们的工作失误使数据库成为系统最脆弱的环节,经受不住偶然事故的冲击。
二. 事故发生过程
6 月 26 日凌晨 12 点左右,我们开始重新建立备份节点的工作,需要把原来的从节点删除,重新安装,所以先使用了 rm -f
方式删除备份节点分区上的所有文件。
5 分钟后,发现刚才删除的是数据库主节点的分区,为防止硬盘继续写入,就马上把 MySQL 进程停止了。所有技术人员开始应急处理。一是把整个分区 dd
成镜像,准备做将来硬盘恢复的备份。二是把 memcache 里的数据 dump 出来,以备可能的恢复。三是重新启用原来的从数据库,由于数据时间只到 4 月 23 日,需要调整近两月表结构变更,让最新的代码可以跑起来。
当天的应急工作至凌晨 4 点,服务器都恢复访问,但数据停留在 4 月 23 日。
在整个应急过程中,部分是紧张,部分是沟通上存在误解,还是出现了失误。当配置从数据库的技术人员完成之后,重启了服务器和 memcache,恢复了正常访问。但是做 memcache 导出工作的技术人员还没有完成,所以最终能从 memcache 里得到的那部分数据只有一半左右。
事后从沃趣科技的数据库工程师那里得知,我们第一时间停止 MySQL 防止硬盘继续写入这个应急措施是错误的,即使分区完全没有文件,MySQL 的进程继续运行,只要保留这个现场,可以从内存中获取更多的数据库结构信息,对恢复数据非常有帮助。
三. 事故后恢复工作
事故后恢复工作从数据来源分为 4 条线索进行:
- 硬盘上数据的恢复(主线)
- 从 memcache 导出的数据恢复
- 从 binlog 里恢复
- 从搜索引擎的快照里恢复页面
以下按时间详细叙述: 6 月 26 日 8 点,我们去机房把服务器硬盘取出来,送到了一家硬盘数据恢复公司。到下午 5 点左右恢复出 ibdata1 文件,文件可能破损。 6 月 26 日 12 点,为了预防新插入的内容和原内容的冲突,我们把所有表的 id 都加到一个大值,半天的内容随后做特殊处理。 6 月 26 日 23 点,导入完了所有 memcache 里的数据。 6 月 27 日上午,从硬盘里又恢复出部分 .ibd 文件,也包含部分数据信息。已确定包含数据的 ibdata1 和 .ibd 文件有破损,无法直接使用,只能尝试从破损文件中提取部分有效信息。 6 月 27 日下午,联系上杭州沃趣网络科技有限公司的陈栋、李春,开始对数据的提取工作。至凌晨 1 点,提取出 .ibd 文件的数据,恢复部分表。 6 月 28 日全天,沃趣科技开始对 ibdata1 文件的提取,至 29 日凌晨 1 点,他们已经提出大部分数据。 6 月 28 日下午,得到阿里巴巴集团的周振兴的友情支持,他开始帮忙做 ibdata1 文件的提取工作,至凌晨 4 点,他完成部分带二进制段的数据表的修复,提取到了相关内容。 6 月 28 日下午,我们联系上北亚数据恢复中心,开始再次尝试对硬盘文件的恢复。 6 月 28 日晚,我们把所有从 binlog 来的数据导入完,完整恢复了最后 10 天的数据。 6 月 29 日中午,从沃趣科技得到的优先级较高的数据表已经恢复完成,开始恢复次优先级的数据。 6 月 30 日中午,提取完所有能从 6 月 27 日获取的破损数据库文件里的所有内容。至此这一阶段提取到缺失总数据量的近 70%。 6 月 30 日下午,开始从搜索引擎快照里抓取部分菜谱重要页面,修补缺失的内容。并联系上某搜索引擎的快照部门,希望获取我们网站的全部页面快照。 7 月 1 日上午,北亚数据恢复中心取得很大的进展,提取到几乎是完整的 ibdata1 文件,至下午 6 点,提取到除了收藏和赞的所有数据表,我们开始把数据导入,至凌晨 4 点,恢复完得到的所有数据。 7 月 2 日整天,由于导入的旧数据和新注册的用户存在部分数据不一致,我们尽力配合用户恢复。 7 月 2 日下午 4 点,北亚提取到 ibdata1 剩下的文件碎片,得到了完整的 ibdata1 文件,MySQL 无报错启动,我们得到了 6 月 26 日凌晨事故前的完整数据库。至凌晨 2 点,我们提取出剩下的收藏和赞,恢复到数据库里。至此损失的数据内容已经恢复到 99%。
下一阶段:
在丢失两个月数据的这一周时间里,用户新产生的数据和恢复的旧数据会有少量不兼容的情况,我们会全力帮助用户找回自己的全部数据,出现的错误敬请用户包涵,帮助我们走过这一过渡阶段。
除了原先的三种备份方式外,我们会继续落实和第三方的云存储方案的合作,把数据备份到我们的服务器之外的地方。
四. 所缺失的近两月数据当前的恢复情况
至今,内容大多得到了 99% 左右的恢复。缺失部分并不是来自硬盘数据丢失,而是 6 月 26 日故障开始到 12 点 id 移位至较大值之前,这半天内创建的内容和原位置内容的冲突,我们还在尽力修补。
以下是当前主要内容的恢复情况:
菜谱 | 收藏 | 赞 | 作品 | 关注 | 菜单 | 用户 | |
---|---|---|---|---|---|---|---|
恢复比例 | 99.0% | 98.6% | 99.2% | 99.5% | 99.5% | 99.3% | 99.1% |
五. 致谢
特别感谢一下 3 个公司和个人在这 7 天的恢复工作中对我们的帮助。
杭州沃趣网络科技有限公司(@沃趣科技)是来自原阿里巴巴 DBA/SA 团队核心骨干组建的创业公司,提供数据库和系统相关的专业服务和产品,陈栋(@grassbell)、李春(@pickup112)对破损的数据库文件进行了灾难修复,提取出绝大部分数据表的内容。
周振兴(@orczhou)是淘宝 MySQL 数据库运维负责人,他对破损文件中部分带二进制段的数据表进行了修复,提取到了相关内容。
北亚数据恢复中心是来自前信息产业部职鉴中心,专门从事数据恢复服务的技术公司。张宇、刘子龙对硬盘文件进行了完整的恢复,使我们得到了数据库的全部数据。