Lỗi SQLite 16 năm tuổi bị chôn vùi gây ra sự cố Tailscale năm ngoái

12 tháng 8, 2026·6 phút đọc

Sau sáu tháng điều tra, Tailscale đã xác định nguyên nhân gây ra loạt sự cố ngừng hoạt động từ cuối năm 2025: một lỗi hiếm gặp trong cơ chế write-ahead log (WAL) của SQLite, tồn tại suốt 16 năm kể từ phiên bản 3.7.0. Lỗi này chỉ xảy ra khi nhiều kết nối cơ sở dữ liệu đồng thời ghi và checkpoint trên cùng một file, và Tailscale là một trong số ít hệ thống kích hoạt nó do tự quản lý quá trình checkpoint.

Lỗi SQLite 16 năm tuổi bị chôn vùi gây ra sự cố Tailscale năm ngoái

Lỗi SQLite 16 năm tuổi bị chôn vùi gây ra sự cố Tailscale năm ngoái

Tailscale vừa công bố kết quả điều tra kéo dài sáu tháng về loạt sự cố ngừng hoạt động bắt đầu từ cuối năm 2025. Nguyên nhân cuối cùng được xác định là một lỗi hiếm gặp trong SQLite, tồn tại âm thầm suốt 16 năm và chỉ bị phát hiện nhờ một công cụ ghi log hoàn toàn mới do chính đội ngũ SQLite phát triển.

Người dùng dịch vụ mạng ngang hàng Tailscale có thể đã trải qua những sự cố ngừng hoạt động bất ngờ bắt đầu từ cuối năm ngoái. Sau cuộc điều tra kéo dài sáu tháng, đội ngũ phát triển cuối cùng đã tìm ra nguyên nhân: một lỗi trong cơ chế write-ahead log (WAL) của SQLite, ẩn nấp suốt 16 năm. Trong bài đăng trên blog hôm thứ Tư, nhóm Tailscale thông báo đã xử lý triệt để vấn đề với sự hỗ trợ từ chính các nhà duy trì SQLite, những người thậm chí phải tạo ra một công cụ mới (được Tailscale tài trợ) để ghi lại hoạt động của virtual file system, giúp truy vết sự cố. Kỹ sư phần mềm Alex Chan của Tailscale mô tả lỗi này đã "chống lại mọi nỗ lực tìm kiếm ban đầu của chúng tôi".

Bản chất của vấn đề

Theo Chan, vấn đề nằm sâu trong bản chất của SQLite – sâu đến mức các nhà duy trì cơ sở dữ liệu này phải thêm mã code để có thể tái hiện lỗi. Để hiểu chuyện gì đã xảy ra, cần biết cách Tailscale hoạt động. Dịch vụ này dựa trên giao thức VPN WireGuard, kết nối trực tiếp các thiết bị trong một mạng lưới mesh riêng ảo. Nó được thiết kế để có độ phức tạp thấp và dễ triển khai, từ việc truy cập NAS từ xa đến kết nối các nhóm làm việc trong một mạng riêng thống nhất. Mỗi mạng mesh (hay "tailnet") nằm trên một trong nhiều máy chủ, nơi cơ sở dữ liệu SQLite quản lý toàn bộ thông tin về các tailnet mà nó lưu trữ.

"Chúng tôi đã sử dụng SQLite làm cơ sở dữ liệu chính từ năm 2022, và chúng tôi chọn nó vì nó được biết đến rộng rãi, đáng tin cậy và phổ biến," Chan viết trong bài phân tích sự cố.

Nhưng một năm trước, có điều gì đó đã diễn ra không đúng. Trong quy trình sao lưu hiện tại, Tailscale chụp một bản snapshot hoàn chỉnh của cơ sở dữ liệu mỗi vài phút, sau đó tải toàn bộ file SQLite lên một S3 bucket. Tuy nhiên, từ tháng 8 năm 2025, các bản sao lưu bắt đầu phát hiện sự hỏng hóc của cơ sở dữ liệu, lặp đi lặp lại mà không có nguyên nhân chung rõ ràng.

Đội ngũ Tailscale không thể tái hiện sự cố vì không có tác nhân kích hoạt đáng tin cậy. Không có mã code cấp thấp nào bị thay đổi trong nhiều tháng. Việc rà soát mọi thứ liên quan đến SQLite cũng không tìm ra điều gì. Làm việc cùng đội ngũ SQLite, nhóm Tailscale đã thử loại trừ các giả thuyết: khóa POSIX bị phá vỡ bởi các lệnh gọi close()? Không phải. Quản lý bộ nhớ sai? Cũng không. SQLite được sử dụng từ nhiều luồng với thread safety bị tắt? Cũng không.

"Sau mỗi sự cố, chúng tôi thu thập thêm dữ liệu, thêm các chẩn đoán và hệ thống loại trừ từng giả thuyết," Chan giải thích.

Lỗi WAL-Reset lộ diện

Nghi vấn dần hướng về quá trình checkpointing của SQLite – cơ chế đưa các mục nhập dữ liệu mới từ một bộ phận tạm thời vào file cơ sở dữ liệu chính. SQLite có một tùy chọn để cải thiện hiệu suất và độ đồng thời, gọi là Write-Ahead Log (WAL). Việc ghi WAL vào cơ sở dữ liệu diễn ra trong một quy trình gọi là checkpoint.

"Trong hầu hết các triển khai, SQLite tự quyết định thời điểm thực hiện checkpoint và quy trình này vô hình đối với người dùng cuối và nhà phát triển. Trong control plane của chúng tôi, chúng tôi tự kiểm soát quy trình checkpoint để có thể chạy sao lưu nhanh và nhất quán," Chan nói.

Đội ngũ SQLite đã tạo một công cụ mới để quan sát kỹ hơn quy trình này: một lớp virtual file system ghi lại hoạt động checkpointing một cách chi tiết. Sau khi chờ đợi sự cố hỏng dữ liệu tiếp theo xảy ra, cả hai nhóm đã có câu trả lời, được đặt tên là lỗi WAL-Reset.

Chan mô tả đó là "một cuộc đua dữ liệu hiếm gặp trong mã nguồn SQLite giữa một checkpoint và một giao dịch ghi". Về cơ bản, đây là sự va chạm giữa quá trình checkpoint và việc ghi dữ liệu vào WAL.

"Nếu một lần ghi xảy ra tại một thời điểm cụ thể trong quá trình checkpoint, quy trình này bị nhầm lẫn – nó nghĩ rằng một số trang đã được sao chép từ WAL vào file cơ sở dữ liệu chính, nhưng thực tế thì chưa," Chan giải thích.

Những trang đó không bao giờ được ghi và vĩnh viễn bị mất, nhưng các trang tham chiếu đến chúng vẫn được ghi, gây ra hỏng hóc cơ sở dữ liệu và dẫn đến hàng loạt vấn đề nghiêm trọng. Theo tài liệu của đội ngũ SQLite, lỗi này chỉ có thể được kích hoạt khi chế độ WAL hoạt động và nhiều kết nối cơ sở dữ liệu mở trên cùng một file. Vì cần phải có đọc và ghi xảy ra đồng thời tại cùng một vị trí bộ nhớ, khả năng xảy ra lỗi là cực kỳ thấp trong hầu hết các tình huống. Việc Tailscale quyết định thực hiện checkpoint thủ công là một ngoại lệ hiếm hoi.

Các nhà duy trì SQLite tin rằng lỗi này đã tồn tại từ phiên bản 3.7.0, phát hành vào tháng 7 năm 2010. Hiện lỗi đã được khắc phục và đội ngũ SQLite khuyến nghị người dùng cập nhật lên phiên bản đã sửa, đồng thời nhấn mạnh rằng lỗi cực kỳ khó xảy ra trong các trường hợp sử dụng thông thường.

"Mặc dù hiếm gặp, lỗi này có hậu quả nghiêm trọng," thông báo của SQLite về WAL-Reset nêu rõ.

Bài học cho các nhà phát triển

Sự cố này mang đến một lời nhắc nhở hữu ích cho các nhà phát triển: ngay cả những phần mềm nhàm chán và đáng tin cậy nhất cũng tiềm ẩn rủi ro khi vận hành theo cách không chuẩn.

"Hầu hết mọi người sử dụng SQLite trong cấu hình tiêu chuẩn và không bao giờ đối mặt với loại vấn đề này. Bằng cách tự kiểm soát quy trình checkpoint và chạy với tốc độ chủ động của riêng mình, chúng tôi đã bước ra khỏi con đường vận hành thông thường," Chan nói.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗