GitLab.com 因主数据库数据被误删宕机数小时,约 5000 个项目数据丢失
来源标题:Postmortem of Database Outage (2017)
GitLab.com 在 2017 年 1 月 31 日因主数据库服务器数据被意外删除而宕机数小时,并永久丢失了部分生产数据。丢失的数据为 UTC 1 月 31 日 17:20 至 00:00 之间的数据库修改,约涉及 5000 个项目和 5000 条评论,以及 700 个新用户账号;代码仓库和 wiki 未受影响。GitLab Enterprise、GitHost 客户及自管理 CE 用户不受影响。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
2017年1月31日,我们的产品之一——在线服务GitLab.com经历了一次重大服务中断。此次中断是由于我们主数据库服务器上的数据被意外删除所致。
这起事件导致GitLab.com服务数小时不可用。我们还丢失了一些生产数据,最终无法恢复。具体而言,我们丢失了1月31日UTC时间17:20至00:00之间对数据库数据的修改,涉及项目、评论、用户账户、issue和snippet等。我们估计大约有5,000个项目、5,000条评论和700个新用户账户受到影响。托管在GitLab.com上的代码仓库或wiki在中断期间不可用,但未受数据丢失影响。GitLab Enterprise客户、GitHost客户以及自管理GitLab CE用户未受此次中断或数据丢失的影响。
丢失生产数据是不可接受的。为确保此类事件不再发生,我们正在对GitLab.com的运维和恢复流程进行多项改进。在本文中,我们将回顾出了什么问题、我们如何恢复,以及我们将采取哪些措施防止未来再次发生。
对于数据丢失的GitLab.com用户以及受中断影响的人们:我们深感抱歉。作为GitLab的CEO,我个人并代表GitLab全体同仁致以歉意。
数据库配置 GitLab.com目前采用单主单备的热备模式。备用服务器仅用于故障转移。在这种配置下,单个数据库必须承担所有负载,这并不理想。主库的主机名为db1.cluster.gitlab.com,备库的主机名为db2.cluster.gitlab.com。
过去,由于db1.cluster.gitlab.com是单点故障,我们在这一特定配置下遇到过各种其他问题。例如:
时间线 1月31日,一位工程师开始在我们的staging环境中搭建多个PostgreSQL服务器。计划是试用pgpool-II,看看能否通过在可用主机之间对查询进行负载均衡来减轻数据库负载。该计划的issue见:infrastructure#259。
± 17:20 UTC:在开始这项工作之前,我们的工程师对生产数据库做了LVM快照并加载到staging环境中。这是为了确保staging数据库是最新的,从而进行更准确的负载测试。此操作通常每24小时自动执行一次(UTC 01:00),但他们希望获得更新版本的数据库副本。
± 19:00 UTC:GitLab.com开始出现数据库负载增加,我们怀疑是垃圾信息所致。在此事件之前的一周内,GitLab.com已经历过类似问题,但没有这么严重。这一负载造成的问题之一是许多用户无法在issue和merge request上发表评论。控制负载花了好几个小时。
我们后来发现,部分负载是由一个后台任务试图删除一名GitLab员工及其关联数据引起的。这是因为该员工的账户被标记为滥用,并被意外安排删除。关于这一问题的更多信息可在issue“Removal of users by spam should not hard delete”中找到。
± 23:00 UTC:由于负载增加,我们的PostgreSQL备库的复制进程开始滞后。复制失败,因为备库所需的WAL段已从主库上删除。由于GitLab.com未使用WAL归档,备库必须手动重新同步。这涉及删除备库上的现有数据目录,并运行pg_basebackup将数据库从主库复制到备库。
一名工程师登录备库,清空了数据目录,然后运行pg_basebackup。不幸的是,pg_basebackup挂起了,尽管设置了--verbose选项,也没有产生有意义的输出。尝试了几次之后,pg_basebackup提示无法连接,因为主库没有足够的可用复制连接(由max_wal_senders选项控制)。
为解决此问题,我们的工程师决定将max_wal_senders从默认值3临时提高到32。在应用设置时,PostgreSQL拒绝重启,声称创建的信号量过多。例如,当max_connections设置过高时就会出现这种情况。在我们的案例中,该值被设为8000。这个值实在太高了,但它是将近一年前设置的,在此之前一直运行正常。为解决此问题,该设置值被降低到2000,PostgreSQL得以顺利重启。
不幸的是,这并没有解决pg_basebackup无法立即启动复制的问题。一名工程师决定用strace运行它,看看它阻塞在哪里。strace显示pg_basebackup挂在一个poll调用上,但这并没有提供任何其他有意义的信息来解释原因。
± 23:30 UTC:一名工程师认为,可能是pg_basebackup在之前几次尝试运行时在备库的PostgreSQL数据目录中创建了一些文件。通常在这种情况下pg_basebackup会打印错误,但该工程师不太确定发生了什么。后来另一位工程师(当时不在场)揭示这是正常行为:pg_basebackup会等待主库开始发送复制数据,在此之前它会静默等待。不幸的是,我们的工程runbook和pg_basebackup官方文档中都没有清楚地记录这一点。
为了恢复复制进程,一名工程师继续清空PostgreSQL数据库目录,错误地以为是在备库上操作。不幸的是,该操作实际执行在了主库上。
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。