Câu chuyện nghề

Ngày một kỹ sư xóa nhầm dữ liệu: câu chuyện GitLab 2017

Ngày 31/1/2017, một kỹ sư GitLab gõ lệnh xóa vào nhầm máy chủ và mất khoảng 300 GB dữ liệu. Rồi cả năm lớp sao lưu đều hỏng. Bài kể lại từng bước theo bản phân tích sau sự cố của chính GitLab, và rút ra danh sách việc nên làm trước khi gõ một lệnh xóa.

  • #sự cố
  • #sao lưu
  • #xóa nhầm
  • #GitLab
  • #hậu kiểm
  • #kỹ thuật vận hành

Bản trình chiếu

Bấm vào slide rồi dùng phím mũi tên để chuyển trang. Phím L đổi ngôn ngữ, phím F để toàn màn hình.

Mở toàn màn hình

Đây là câu chuyện có thật, nhưng không phải chuyện của mình. Mình kể lại theo bản phân tích sau sự cố do chính GitLab công bố ngày 10/2/2017 (link ở cuối bài). Mình không đặt tên người kỹ sư: bản ghi ban đầu của GitLab có nêu tên, và họ cũng nói sẽ ẩn tên trong các sự cố về sau.

Mình không biết người đó nghĩ gì hay cảm thấy gì lúc đó, nên bài không tả điều đó như sự thật. Phần nào là mình suy luận hoặc gợi ý, mình ghi rõ.


Tóm tắt nhanh#

  • Ngày 31/1/2017, trong lúc dựng lại máy chủ phụ của cơ sở dữ liệu GitLab.com, một kỹ sư chạy lệnh xóa trên máy chủ chính thay vì máy chủ phụ. Khoảng 300 GB bị xóa trước khi lệnh bị dừng, chỉ sau một hai giây.
  • Rồi các lớp sao lưu lần lượt hỏng hoặc không dùng được. Bản duy nhất khôi phục được là một ảnh chụp tình cờ do chính kỹ sư đó chụp thủ công khoảng 6 giờ trước.
  • Dịch vụ ngừng khoảng 18 giờ. GitLab ước tính mất ít nhất 5.000 dự án, 5.000 bình luận và khoảng 700 tài khoản mới. Kho mã Git và wiki không bị ảnh hưởng.
  • Gõ nhầm lệnh chỉ là mắt xích cuối. Trước đó đã có tải tăng vọt, thủ tục làm tay thiếu tài liệu, sao lưu hỏng không ai biết.
  • GitLab công khai mọi thứ: một tài liệu chung, phát trực tiếp việc khôi phục và một bản phân tích dài. Điều đó đáng học không kém bài học kỹ thuật.

Từ khó, nói dễ#

Thuật ngữ Nói dễ hiểu
Máy chủ chính (primary) Máy cơ sở dữ liệu đang chạy thật, nhận mọi thay đổi của người dùng.
Máy chủ phụ (secondary) Máy sao chép lại máy chính theo thời gian thực, để thay thế khi máy chính hỏng.
Sao chép đồng bộ (replication) Máy phụ liên tục nhận bản ghi thay đổi từ máy chính để giữ giống hệt.
Sao lưu (backup) Bản sao dữ liệu để khôi phục sau sự cố. Khác với sao chép đồng bộ.
Ảnh chụp (snapshot) Bản chụp trạng thái ổ đĩa tại một thời điểm.
Khôi phục thảm họa Lấy lại dịch vụ sau khi mất dữ liệu nghiêm trọng.
Phân tích sau sự cố (postmortem) Bản viết lại sự cố: chuyện gì xảy ra, vì sao, sửa gì.
Không đổ lỗi (blameless) Cách phân tích tập trung vào hệ thống và quy trình, không tìm người để trách.

1. Một ngày bình thường, rồi bắt đầu xấu đi#

Tất cả giờ dưới đây theo múi giờ UTC, ngày 31/1/2017.

Khoảng 17:20. Một kỹ sư chụp ảnh ổ đĩa của cơ sở dữ liệu sản xuất và nạp vào môi trường thử, để thử nghiệm tải cho một bộ cân bằng kết nối. Thao tác này vốn do hệ thống tự làm mỗi ngày lúc 01:00. Lần chụp thủ công này sẽ trở thành thứ cứu cả đêm đó, nhưng lúc ấy chưa ai biết.

Khoảng 19:00. Tải cơ sở dữ liệu tăng vọt. Nhóm nghi do thư rác, nhiều người không đăng được bình luận. Một phần tải đến từ một tiến trình nền xóa dữ liệu của một nhân viên GitLab vì tài khoản người này bị hệ thống báo cáo lạm dụng gắn nhầm và đặt lịch xóa. Theo GitLab, hệ thống báo cáo lạm dụng khiến người xử lý dễ bỏ sót chi tiết.

Khoảng 23:00. Máy phụ chậm dần rồi ngừng sao chép: nó cần những đoạn nhật ký thay đổi mà máy chính đã dọn mất, và GitLab.com lúc đó không lưu trữ chúng để dùng lại. Cách duy nhất là dựng lại máy phụ từ đầu bằng tay.

Nhóm bắt đầu làm. Công cụ dựng lại treo im lặng, không báo gì. Họ chỉnh các tham số, rồi PostgreSQL không chịu khởi động lại, và lại chỉnh tiếp. Đây là kiểu đêm mà ai làm vận hành cũng quen: một việc nhỏ kéo theo nhiều việc nhỏ, và mỗi bước đều có vẻ hợp lý.


2. Khoảng 23:30: một lệnh, vào nhầm máy#

Để dựng lại sao chép, cần xóa sạch thư mục dữ liệu của máy phụ rồi nạp lại. Theo bản phân tích của GitLab, kỹ sư chạy lệnh xóa đó trên máy chủ chính.

Họ dừng lệnh sau khoảng một hai giây. Nhưng khoảng 300 GB dữ liệu đã bị xóa.

Mình không có cách nào biết điều gì diễn ra trong đầu người đó, và bài không đoán. Điều có thể nói chắc là sau sự cố, GitLab đưa vào danh sách việc cần làm một mục rất giản dị: làm cho dấu nhắc lệnh cho biết rõ bạn đang ở máy nào và môi trường nào. Chỉ riêng mục đó cho thấy họ thấy việc phân biệt hai máy lúc đó chưa đủ rõ.


3. Đi tìm bản sao lưu: năm lớp, không lớp nào dùng được#

Ngay sau đó họ đi tìm bản sao lưu. Đây là phần khiến câu chuyện trở thành bài học:

Lớp bảo vệ Chuyện gì xảy ra
Sao lưu hằng ngày (pg_dump) Chạy sai phiên bản công cụ so với cơ sở dữ liệu thật nên hỏng. Chỗ lưu trên đám mây rỗng. Thông báo lỗi gửi bằng email nhưng bị từ chối vì thiếu cấu hình xác thực email, nên không ai biết.
Ảnh chụp ổ đĩa đám mây Có cho máy chủ tệp nhưng chưa bật cho máy chủ cơ sở dữ liệu, vì cho rằng các lớp khác đã đủ.
Ảnh chụp LVM Chụp mỗi 24 giờ, lập ra để sao chép sang môi trường thử chứ không phải để khôi phục thảm họa. Chỉ có một bản thủ công khoảng 6 giờ trước.
Sao chép sang máy phụ Làm cho dự phòng khi hỏng máy, không phải khôi phục thảm họa. Và máy phụ vừa bị xóa trắng để dựng lại.
Bản sao ở môi trường thử Có dữ liệu, nhưng nằm trên ổ đĩa chậm ở một vùng khác.

Hai điểm đáng nhớ. Thứ nhất, mỗi lớp đều hỏng vì một lý do khác nhau và đều có lý do nghe hợp lý. Thứ hai, theo GitLab, việc sao lưu không có người chịu trách nhiệm, nên không ai kiểm tra thường xuyên xem chúng có khôi phục được không.


4. Khôi phục: 18 giờ chép dữ liệu#

Nhóm chọn ảnh chụp thủ công 6 giờ trước, vì mất ít dữ liệu hơn bản 24 giờ.

  • Dữ liệu nằm trên ổ đĩa chậm của môi trường thử, và việc chép về máy sản xuất mất khoảng 18 giờ. Ổ đĩa bị giới hạn ở khoảng 60 Mbps, và nút thắt là ổ đĩa.
  • Cơ sở dữ liệu được khôi phục về trạng thái lúc 17:20 UTC ngày 31/1.
  • 17:00 UTC ngày 1/2: GitLab.com chạy lại, tạm thời chưa có webhook. Webhook sau đó được dựng lại từ một bản trích riêng.
  • Bộ đếm mã số trong cơ sở dữ liệu được cộng thêm 100.000 để tránh dùng lại mã số đã cấp trước sự cố.
  • Kiểm tra cuối hoàn tất khoảng 18:00 UTC cùng ngày.

Thiệt hại. Theo GitLab, ước tính ít nhất 5.000 dự án, 5.000 bình luận và khoảng 700 tài khoản mới bị mất thay đổi trong khoảng từ 17:20. (Bản phân tích ghi mốc cuối khoảng 23:30 ở phần thiệt hại và 00:00 ở phần mở đầu, nên đừng coi mốc đó là chính xác tuyệt đối.) Các dự án tạo sau 17:20 chỉ khôi phục được kho mã, không có vấn đề (issue) và yêu cầu hợp nhất (merge request). Kho mã Git và wiki không bị ảnh hưởng vì lưu riêng, và khách hàng tự cài đặt cũng không bị ảnh hưởng.


5. Cách GitLab xử lý trước công chúng#

Đây là phần mình thấy đáng học nhất, ngoài kỹ thuật.

  • Nhóm duy trì một tài liệu chung công khai ghi lại từng bước.
  • Họ phát trực tiếp việc khôi phục trên YouTube, cao điểm khoảng 5.000 người xem, và cập nhật trên Twitter.
  • Họ công bố bản phân tích dài chỉ mười ngày sau, kèm danh sách khoảng 15 việc cần làm.
  • Họ nhận rằng tài liệu ban đầu đã nêu tên người kỹ sư, và hứa ẩn tên trong các sự cố sau.

Cách làm này thường gọi là không đổ lỗi: coi lỗi của một người là dấu hiệu hệ thống cho phép lỗi đó xảy ra, và hỏi "làm sao để lần sau không ai có thể nhầm như vậy" thay vì "ai nhầm".


6. Lệnh gõ nhầm chỉ là mắt xích cuối#

Nếu bóc chuyện này theo bản phân tích, một lệnh nhầm đứng sau cả một chuỗi:

  1. Tải tăng vọt vì thư rác và một tiến trình xóa dữ liệu chạy nhầm.
  2. Máy phụ ngừng sao chép vì hệ thống không lưu trữ nhật ký thay đổi.
  3. Thủ tục dựng lại làm tay, thiếu tài liệu, công cụ treo im lặng.
  4. Sao lưu hằng ngày hỏng âm thầm, thông báo bị chặn.
  5. Ảnh chụp đám mây chưa bật cho cơ sở dữ liệu.
  6. Không ai làm chủ việc sao lưu và thử khôi phục.
  7. Hai máy dễ nhầm, dấu nhắc lệnh không phân biệt.

Trong chuỗi đó, gõ nhầm có lẽ là mắt xích khó tránh nhất ở mức cá nhân, và là mắt xích dễ tránh nhất ở mức hệ thống.


7. GitLab đã sửa những gì#

Trong danh sách hành động công khai của GitLab có các mục như:

  • Làm rõ máy và môi trường trong dấu nhắc lệnh.
  • Giám sát sao lưu bằng bảng theo dõi công khai.
  • Ảnh chụp LVM mỗi giờ cho cơ sở dữ liệu sản xuất (GitLab ghi là đã làm xong).
  • Bật ảnh chụp ổ đĩa đám mây cho máy chủ cơ sở dữ liệu.
  • Tự động thử khôi phục sao lưu.
  • Khôi phục theo thời điểm bằng lưu trữ nhật ký liên tục.
  • Tài liệu và quy trình cho việc dựng lại sao chép.
  • Giao một người làm chủ độ bền của dữ liệu.

Đáng chú ý là GitLab nói họ tập trung vào khả năng khôi phục và nhận diện máy rõ ràng, thay vì chỉ cố chặn lệnh nguy hiểm. Họ coi gõ nhầm là điều sẽ lại xảy ra, và muốn hậu quả của nó nhỏ.


8. Mình rút ra gì: sáu mươi giây trước khi gõ lệnh xóa#

Phần này là gợi ý của mình, không phải kết luận của GitLab.

  1. Bạn đang ở máy nào? Đọc tên máy trên dấu nhắc, không đoán. Nếu hai máy trông giống nhau, đổi màu dấu nhắc cho máy thật.
  2. Bạn đang ở thư mục nào? In đường dẫn hiện tại trước khi xóa.
  3. Chạy thử ở chế độ chỉ liệt kê. Xem nó sẽ xóa gì trước khi xóa thật.
  4. Bản sao lưu có thật không? Không phải "chắc là có", mà là bạn đã khôi phục thử và thấy dữ liệu về.
  5. Người thứ hai nhìn màn hình. Với dữ liệu sản xuất, một cặp mắt nữa rất rẻ.
  6. Đừng làm khi quá mệt hoặc đang vá lỗi dở. Dừng, nghỉ, rồi làm. Điều này mình suy luận từ kinh nghiệm chung, bản phân tích của GitLab không nói người kỹ sư đó mệt.
  7. Có kế hoạch cho phút đầu tiên sau khi nhầm. Dừng lệnh, báo ngay cho người khác, đừng cố tự sửa lặng lẽ. Việc kỹ sư dừng lệnh sau một hai giây ở đây đã cứu được phần còn lại.

9. Khi AI có quyền chạy lệnh#

Câu chuyện này xảy ra năm 2017, trước khi có các AI agent chạy lệnh thay người. Nhưng nó gợi ý một điều: mỗi AI agent có quyền xóa là một người gõ lệnh không bao giờ mệt, và cũng không bao giờ cảm thấy "có gì sai sai". Bài Vì sao không nên tin AI tuyệt đối nhắc đến một vụ việc công khai khác, và bài MCP là gì nói về cầu chì cho AI: quyền tối thiểu, bắt đầu bằng chỉ đọc, người duyệt việc nhạy cảm. Những nguyên tắc đó chính là các bài học của GitLab, áp dụng cho một người gõ lệnh mới.


10. Nhìn cân bằng#

  • Đây là một nguồn chính. Mình dựa chủ yếu vào bản phân tích của chính GitLab. Một số chi tiết khác nhau giữa các bản ghi (ví dụ mốc cuối của khoảng thời gian mất dữ liệu).
  • Mình không biết người kỹ sư cảm thấy gì. Bài không tả cảm xúc như sự thật.
  • Sự cố này đã gần 10 năm. Công cụ đổi nhiều, nhưng các nguyên nhân (sao lưu chưa thử, không có người làm chủ, nhầm máy) vẫn rất quen.
  • "Không đổ lỗi" không có nghĩa là không có trách nhiệm. Nó chuyển trách nhiệm từ một người sang hệ thống và những người thiết kế hệ thống.

11. Kết luận#

Một kỹ sư gõ nhầm một lệnh. Nhưng thứ làm câu chuyện đau là cả năm lớp sao lưu đều không dùng được đúng lúc cần. Bài học nằm ở hai chỗ: làm cho lệnh nhầm khó xảy ra hơn, và làm cho hậu quả của nó nhỏ khi vẫn xảy ra.

Việc nhỏ làm ngay: chọn một bản sao lưu bạn đang tin tưởng, và thử khôi phục nó trong tuần này. Nếu chưa từng thử, bạn chưa có bản sao lưu, bạn chỉ có hy vọng.

Nếu bạn có chuyện xóa nhầm dữ liệu của chính mình, hãy viết ra bằng cách trả lời bảy câu hỏi: chuyện xảy ra khi nào, bạn đã làm gì trước đó, mất gì, phát hiện thế nào, khôi phục ra sao, sau đó đổi điều gì, và điều bạn muốn người khác rút ra.


Nguồn tham khảo#

Câu hỏi thường gặp

Chuyện gì đã xảy ra với GitLab.com ngày 31/1/2017?
Theo bản phân tích sau sự cố của GitLab, khi đang dựng lại máy chủ phụ của cơ sở dữ liệu, một kỹ sư chạy lệnh xóa dữ liệu trên máy chủ chính thay vì máy chủ phụ. Khoảng 300 GB dữ liệu bị xóa trước khi lệnh bị dừng. Dịch vụ ngừng khoảng 18 giờ và mất dữ liệu trong khoảng từ 17:20 UTC, ước tính ít nhất 5.000 dự án, 5.000 bình luận và khoảng 700 tài khoản.
Vì sao các bản sao lưu đều không dùng được?
Mỗi lớp hỏng vì một lý do khác nhau: bản sao lưu hằng ngày chạy sai phiên bản công cụ nên rỗng và thông báo lỗi bị từ chối vì thiếu cấu hình email, ảnh chụp ổ đĩa đám mây chưa bật cho máy chủ cơ sở dữ liệu, ảnh chụp LVM chỉ chụp mỗi 24 giờ và vốn dùng để sao chép sang môi trường thử, còn bản sao đồng bộ thì làm cho dự phòng chứ không phải khôi phục thảm họa. Không ai làm chủ việc kiểm tra sao lưu.
Lỗi này là lỗi của một người?
Chính GitLab không coi như vậy. Bản phân tích liệt kê một chuỗi nguyên nhân: tải tăng đột biến, quy trình dựng lại máy chủ phụ làm thủ công và thiếu tài liệu, sao lưu hỏng âm thầm và không ai chịu trách nhiệm. Lệnh gõ nhầm là mắt xích cuối. GitLab cũng nói sẽ ẩn tên người trong các sự cố sau.
Nên làm gì trước khi gõ một lệnh xóa?
Kiểm tra bạn đang ở máy nào (tên máy, thư mục), chạy thử ở chế độ chỉ liệt kê nếu có, chắc chắn đã có bản sao lưu và từng thử khôi phục nó, và nếu có thể, nhờ người thứ hai nhìn vào màn hình. Nhiều tổ chức còn đặt dấu nhắc lệnh khác màu cho máy chủ thật, như GitLab ghi trong danh sách việc cần làm sau sự cố.