Мэдээ

Tailscale ба SQLite: 16 Жилийн Настай WAL-Reset Багийг Илрүүлсэн Түүх

TOGTOKHTOGTOKH·2026 оны наймдугаар сарын 12·3 үзсэн·
Tailscale ба SQLite: 16 Жилийн Настай WAL-Reset Багийг Илрүүлсэн Түүх

Эхлэл: Чулуу Шиг Бат Бөх SQLite Дата Баазад Үүссэн Нууцлаг Алдаа

SQLite бол дэлхий дээр хамгийн олон төхөөрөмж дээр ажилладаг, найдвартай ажиллагаагаараа алдартай, суулгагддаг (embedded) реляци дата бааз билээ. Веб хөтөч, гар утасны аппликейшнээс эхлээд томоохон сүлжээний дэд бүтэц хүртэл SQLite-ийг сая сая веб ба аппликейшнд өргөнөөр ашигладаг. Гэвч Tailscale сүлжээний платформын инженерүүд Amazon S3 руу хийдэг автомат нөөц хуулбаруудаа (backup) шинжлэх явцад цөөнгүй дата бааз дээр PRAGMA integrity_check комманд ажиллуулахад дата бааз эвдэрсэн (corrupted) байх ноцтой тохиолдолтой тулгарчээ.

SQLite-ийн файлын бүтэц эвдрэх нь практикт маш ховор тохиолддог үзэгдэл юм. Тиймээс Tailscale-ийн инженерүүд 6 сар гаруй хугацаанд мөрдлөг хийж, эцэст нь SQLite-ийн эх кодод 2010 оноос буюу 16 жилийн турш илрээгүй нуугдаж байсан "WAL-Reset" заналхийт багийг олж тодорхойлсон байна.

WAL Горим ба WAL-Reset Гэж Юу Вэ?

SQLite дата бааз нь олон унших болон бичих үйлдэлийг нэгэн зэрэг (concurrency) хурдан бөгөөд аюулгүй гүйцэтгэхийн тулд Write-Ahead Logging (WAL) горимыг ашигладаг.

Стандарт горимд SQLite бичилт бүрээр дата баазын үндсэн .db файлыг шууд түгжин өөрчилдөг бол WAL горимд:

  • Шинэ өөрчлөлтүүд шууд үндсэн .db файл руу бичигдэхийн оронд эхлээд тусдаа -wal гэсэн лог файл руу дарааллан нэмэгдэж бичигддэг.
  • Дараа нь checkpoint хэмээх тусгай процессоор -wal файл дахь хуудсуудыг (pages) үндсэн дата бааз руу шилжүүлж адилтгадаг.
  • Чекпойнт хийгдэж дууссаны дараа SQLite нь WAL файлын эхэн рүү буцаж, дараагийн бичилтүүдийг дээрээс нь давхарлан бичих боломжтой болгодог. Үүнийг WAL-Reset эсвэл Wraparound гэж нэрлэдэг.

Уг механизмын ачаар уншиж буй процессууд бичиж буй процесст саад болохгүйгээр өгөгдлийг хурдан унших боломж бүрэлддэг юм.

16 Жилийн Настай "Race Condition" Алдаа Хэрхэн Үүссэн Бэ?

Tailscale-ийн инженерүүдийн гүнзгий шинжилгээгээр уг баг нь SQLite 3.7.0 (2010 оны 7-р сард гарсан) хувилбараас эхлэн оршин байжээ.

Асуудлын гол шалтгаан нь олон процесс эсвэл срэд (threads) нэгэн зэрэг дата бааз руу бичиж, нэгэн зэрэг чекпойнт хийх үед үүсдэг маш нарийн Race Condition (ажиллагааны зөрчил) байв. Асуудал яг яаж явагддаг вэ?

  1. Бичих үйлдэл ба Чекпойнт Зэрэгцэх: Нэг процесс эсвэл срэд чекпойнт хийж дуусгаад WAL файлын санах ойг reset хийхээр бэлтгэж байх яг тэр хоромд өөр нэг процесс шинэ транзакц нээж, WAL руу шинэ хуудас бичдэг.
  2. Өгөгдөл Дарагдаж Арчигдах: Чекпойнт хийж буй процесс WAL-ийн заагчийг reset хийхдээ дөнгөж бичигдсэн шинэ өгөгдлийг үндсэн дата бааз руу хуулагдаж амжаагүй байхад нь "хүчингүй" гэж үзэн дээрээс нь давхарлан бичих боломжтой болгодог.
  3. Дата Баазын Эвдрэл: Үүний дараагийн бичилтүүд хуучин хуудсуудыг арилгаснаар индекс болон хүснэгтийн өгөгдлийн зөрүү үүсэж, дата бааз эвдэрч буюу SQLITE_CORRUPT алдаа мэдээлдэг.

Энэхүү алдаа нь секундэд хэдэн мянган транзакц хийгддэг, олон процесс нэг дата бааз руу зэрэг ханддаг тусгай нөхцөлд л тохиолддог бөгөөд уламжлалт нэгж тестүүдэд (unit tests) илрэх боломжгүй бараг "сүнстэй" алдаа байв.

Нээлттэй Эхийн Хамтын Ажиллагаа ба Шийдэл

Tailscale компани уг асуудлыг бүрэн тусгаарлаж, баталгаажуулахын тулд нээлттэй эхийн SQLite VFS (Virtual File System) shim хэрэгслийн хөгжүүлэлтийг санхүүжүүлсэн байна. Уг хэрэгсэл нь операцийн системийн файлын систем ба SQLite-ийн хоорондох I/O дуудлагуудыг микросекундын түвшинд логдож, алдаа гарах агшинг яг таг барьж чаджээ.

Түүнчлэн програм хангамжийн найдвартай байдлыг шалгадаг Antithesis систем болон TLA+ математик загварчлалыг ашиглан SQLite-ийн код доторх логик зөрчлийг баталгаажуулсан байна.

Ингээд SQLite-ийн ахлах хөгжүүлэгч Дэн Кеннеди (Dan Kennedy)-д асуудлын кэйсийг хүргүүлснээр SQLite баг алдааг албан ёсоор хүлээн зөвшөөрч, SQLite 3.51.3 болон 3.53.0 хувилбаруудад засаврыг нэгтгэжээ.

Засавар нь зарчмын хувьд маш товч бөгөөд чекпойнт эхэлснээс хойш WAL файл дээр ямар нэгэн reset хийгдсэн эсэхийг шалгах нэмэлт шалгуур (check) код суулгаснаар уг race condition-ийг бүрэн арилгасан байна.

Программ Хөгжүүлэгчдэд Өгөх Сургамж

Энэхүү техникийн кэйс нь программ хөгжүүлэгчид, архитектурууд болон DevOps инженерүүдэд хэд хэдэн чухал санамжийг өгч байна:

  • SQLite Хувилбараа Яаралтай Шинэчлэх: Хэрэв таны систем Go, Python, Node.js эсвэл C/C++ дээр SQLite-ийн WAL горимыг олон срэд/процессоос нэгэн зэрэг ашиглаж байгаа бол SQLite сангаа 3.51.3 эсвэл 3.53.0+ хувилбар руу НЭН ДАРУЙ шинэчлэх шаардлагатай.
  • Нөөц Хуулбарын Валидаци (Backup Integrity Check): "Backup амжилттай хийгдлээ" гэсэн статус нь дата бааз эрүүл гэсэн үг биш. Автоматаар нөөцөлсөн дата бааз бүр дээрээ PRAGMA integrity_check комманд ажиллуулж эвдрэл байгаа эсэхийг байнга шалгаж хэвших нь зүйтэй.
  • Нээлттэй Эхийг Санхүүжүүлж Дэмжих: Tailscale шиг томоохон технологийн компани өөрсдийн ашигладаг Open Source санг зөвхөн ашиглаад зогсохгүй, тусгай хэрэгсэл хөгжүүлэхэд хөрөнгө оруулалт хийснээр дэлхий даяар сая сая системд тулгарч болох том эрсдэлийг хааж чадлаа.

Эх сурвалж: https://tailscale.com/blog/sqlite-wal-reset-bug

Сэтгэгдэл

Ачаалж байна...