12 คะแนน โดย GN⁺ 2025-12-13 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Litestream VFS เป็นส่วนขยายแบบปลั๊กอินที่ทำให้สามารถอ่านและคิวรีฐานข้อมูล SQLite ได้โดยตรงจาก object storage (เช่น S3)
  • สามารถ คิวรีจากไฟล์แบ็กอัประยะไกลได้ทันที และทำ Point-in-Time Recovery (PITR) ได้โดยไม่ต้องดาวน์โหลดฐานข้อมูลทั้งหมด
  • ภายในใช้ ฟอร์แมต LTX เพื่อจัดการชุดของเพจที่เปลี่ยนแปลงอย่างมีประสิทธิภาพ และเพิ่มความเร็วในการกู้คืนด้วย compaction ที่ข้ามเพจซ้ำ
  • ใช้ อินเทอร์เฟซ VFS ของ SQLite เพื่อดักจับเฉพาะการอ่าน ส่วนการเขียนยังให้โปรเซส Litestream เดิมจัดการ
  • ด้วยการแบ็กอัประดับวินาทีและการอัปเดตดัชนี จึงให้ รีพลิกาที่เกือบเรียลไทม์ และรองรับการคิวรีได้รวดเร็วในสภาพแวดล้อมคลาวด์

ภาพรวมของ Litestream VFS

  • Litestream VFS เป็นความสามารถที่ทำให้ SQLite ใช้ URL ของ object storage เป็นแหล่งข้อมูลได้โดยตรง
    • เปิดใช้งานจาก SQLite shell ด้วยคำสั่ง .load litestream.so และ .open file:///my.db?vfs=litestream
    • หลังจากนั้นสามารถรันคิวรีโดยอิงจากไฟล์แบ็กอัปที่เก็บไว้บน S3 ได้
  • สามารถ คิวรีจากแบ็กอัประยะไกลได้โดยตรง โดยไม่ต้องดาวน์โหลดฐานข้อมูลทั้งหมด
    • ในตัวอย่าง ใช้คิวรี SELECT * FROM sandwich_ratings เพื่อดูข้อมูลบางส่วนที่เก็บอยู่บน S3 ได้ทันที

ความสามารถ Point-in-Time Recovery (PITR)

  • ใช้คำสั่ง PRAGMA litestream_time = '5 minutes ago'; เพื่อ ดูสถานะข้อมูล ณ ช่วงเวลาที่ต้องการ ได้
    • ระบุได้ทั้งเวลาแบบสัมพัทธ์ (5 minutes ago) หรือเวลาแบบแน่นอน (2000-01-01T00:00:00Z)
  • ทำให้สามารถทำ Point-in-Time Recovery ได้ทันทีในระดับ SQL
    • ในตัวอย่าง หลังจากรัน UPDATE ผิดพลาด ก็ย้อนกลับไปดูสถานะเมื่อ 5 นาทีก่อนได้และยืนยันว่าข้อมูลถูกต้อง

ฟอร์แมต LTX และการบีบอัดข้อมูล

  • Litestream v0.5 ได้รวมฟอร์แมต LTX (Litestream Transaction eXchange) เข้าไว้
    • เวอร์ชันก่อนหน้าจะส่งทั้ง SQLite page เต็ม ๆ แต่ LTX จะส่งเฉพาะ ชุดของเพจที่มีลำดับ
  • แกนสำคัญของ LTX คือความสามารถ “compaction” ที่เลือกใช้เฉพาะเพจเวอร์ชันล่าสุดตอนกู้คืน
    • ตัวอย่าง: จาก 1 2 3 5 3 5 4 5 5 จะใช้เพียง 5, 4, 3, 2, 1 ตัวขวาสุดเท่านั้น
  • LTX สามารถบีบอัดได้ไม่ใช่แค่ทั้งฐานข้อมูล แต่รวมถึง ระหว่างชุดไฟล์ LTX ด้วย ทำให้รองรับ การกู้คืนแบบ PITR ได้
  • ใน trailer ของไฟล์ LTX จะมีดัชนีออฟเซ็ตของแต่ละเพจรวมอยู่ด้วย ดังนั้น
    • จึงอ่านเฉพาะเพจที่ต้องใช้ผ่าน คำขอ S3 Range ได้โดยไม่ต้องดาวน์โหลดทั้งไฟล์

วิธีการทำงานของ VFS

  • Litestream VFS ถูกสร้างขึ้นโดยใช้ อินเทอร์เฟซ VFS (Virtual File System) ของ SQLite
    • VFS คือโครงสร้างปลั๊กอินที่ทำหน้าที่แยกชั้นการเข้าถึงระบบปฏิบัติการของ SQLite
  • Litestream VFS จัดการเฉพาะการ อ่าน (Read) ส่วน การเขียน (Write) ยังเป็นหน้าที่ของโปรเซส Litestream เดิม
  • เมื่อ SQLite อ่านเพจ VFS จะทำการแมปตาม ดัชนีของเพจ แทนการใช้ออฟเซ็ตไบต์ที่ร้องขอ
    • จากนั้นค้นหาชื่อไฟล์ ออฟเซ็ตจริง และขนาดเพจจากดัชนี แล้วดาวน์โหลดเฉพาะบล็อกนั้นผ่าน Range header ของ S3 API
  • มีการใช้ LRU cache เพื่อเก็บ “hot page” ที่ถูกเข้าถึงบ่อยไว้ในหน่วยความจำ ลดจำนวนการเรียก S3 ให้น้อยที่สุด

การรีพลิกาแบบเรียลไทม์และประสิทธิภาพ

  • Litestream ทำ แบ็กอัประดับ L0 ทุก ๆ หนึ่งวินาที
    • VFS จะโพลเส้นทางบน S3 เป็นระยะเพื่อ อัปเดตดัชนีแบบค่อยเป็นค่อยไป
    • ผลลัพธ์คือได้ รีพลิกาที่เกือบเรียลไทม์ (near-realtime replica)
  • พร้อมใช้งานได้ทันทีโดยไม่ต้องสตรีมฐานข้อมูลทั้งหมด
  • โครงสร้างนี้ช่วยให้ได้ทั้ง การเริ่มต้นที่รวดเร็ว และ เวลาในการกู้คืนที่สั้น

การใช้งานและความสำคัญ

  • Litestream เก็บแบ็กอัปของทุกสถานะในฐานข้อมูลไว้ด้วย ความละเอียดระดับวินาที
    • หากพลาด DELETE หรือ UPDATE ก็สามารถกู้กลับไปยังเวลาที่ต้องการได้ทันที
  • ด้วยโครงสร้างที่คิวรีได้โดยตรงจาก object storage จึงทำงานได้รวดเร็วแม้ใน สภาพแวดล้อมเซิร์ฟเวอร์แบบ ephemeral
  • ใช้ความสามารถพื้นฐานของ SQLite โดยไม่ต้องมีกลไกซับซ้อน จึงให้ ระบบแบ็กอัปและกู้คืนที่เรียบง่ายแต่ทรงพลัง
  • มีการใช้งานอยู่ใน API ภายในของ Fly.io ด้วย และสามารถใช้งานได้อย่าง เสถียรในสภาพแวดล้อม production

1 ความคิดเห็น

 
GN⁺ 2025-12-13
ความคิดเห็นจาก Hacker News
  • โอ้ อันนี้ใช้ sqlite vfs module สำหรับ Go ที่ฉันทำไว้
    ทุกครั้งที่รู้ว่าโค้ดที่ฉันทำช่วยคนอื่นได้ก็รู้สึกดีใจมาก
    psanford/sqlite3vfs
    • ใช้งานได้ดีมาก ขอบคุณสำหรับสิ่งนี้
    • สุดท้ายแล้วนี่แหละคือช่วงเวลาแบบที่เราต้องการในชีวิต
  • อันนี้เจ๋งมาก Litestream VFS สะท้อนแนวคิดแบบยูนิกซ์ได้อย่างชัดเจน
    SQLite ทำงานเหมือนเดิมตามปกติ และ Litestream ก็ทำงานอย่างโปร่งใสอยู่ด้านบน
    นั่นหมายความว่าสามารถทำ การกู้คืนแบบ point-in-time (PITR) ได้ด้วยแค่ SQL และ SQLite pragma
    ทำให้ค้นดูข้อมูลในอดีตได้อย่างรวดเร็วโดยไม่ต้องไปแตะชุดข้อมูลโปรดักชันโดยตรง
  • การออกแบบอินเทอร์เฟซสะอาดมาก
    แค่ระบุ S3 bucket ด้วย environment variable แล้วใน SQLite ก็ .load litestream.so จากนั้น
    ใช้ PRAGMA litestream_time = '5 minutes ago'; เพื่อดูข้อมูล ณ เวลาก่อนหน้าได้ทันที
    • บน macOS หลังจาก brew install sqlite3 แล้ว
      ต้อง ระบุชื่อ init function เองโดยตรง แบบ .load litestream sqlite3_litestreamvfs_init
  • ใช้งานกับ bun:sqlite ได้สำเร็จเหมือนกัน
    แค่ตั้งค่า "LITESTREAM_REPLICA_URL" กับ environment variable ของ AWS key
    จากนั้นโหลดส่วนขยายด้วย temp.loadExtension("/path/to/litestream.dylib", "sqlite3_litestreamvfs_init")
    แล้วเปิดด้วย file:my.db?vfs=litestream ก็ใช้ได้เลย
    • สงสัยว่านี่ตั้งใจให้ใช้หลัก ๆ ในสภาพแวดล้อม JavaScript server (bun) หรือเปล่า
    • เยี่ยมเลยที่มันทำงานได้ แต่ก็สงสัยว่าหา path ของไฟล์ .dylib เจอได้อย่างไร
    • เผื่อไว้เป็นข้อมูล ในตัวอย่างนี้ส่วนตั้งค่า environment variable ใช้ dotenv ไม่ได้ผล ต้องกำหนดตอนรันโดยตรงเท่านั้น
  • ฟีเจอร์นี้เจ๋งมาก
    กรณีใช้งานของฉันคือใช้ SQLite DB แบบอ่านอย่างเดียว ที่เก็บอยู่บน S3 โดยตรงกับเว็บไซต์
    DB จะถูกอัปเดตด้วยงาน cron อะไรทำนองนั้น ส่วนเว็บไซต์ก็อ่านข้อมูลล่าสุดผ่าน Litestream VFS อย่างเดียว
    อยากรู้ว่าใช้งานแบบนี้ได้ไหม และมี Python integration module หรือเปล่า
    ตอนนี้แอป Flask ของฉันดึงข้อมูลจาก Google Spreadsheet มาแปลงเป็น SQLite แล้วอัปเดตรายวัน
    ดูโค้ดแอปของฉัน
    • ผู้เขียนเอง Litestream VFS จะ poll ข้อมูลแบ็กอัปอัตโนมัติทุก 1 วินาที เพื่อให้ทันสมัยอยู่เสมอ
      และทำงานได้ตรง ๆ ใน SQLite CLI โดยไม่ต้องมีโค้ด Python เพิ่มเติม
    • ถ้าใช้งานคล้ายกัน ขอแนะนำ ZeroFS ด้วย
      ใช้แค่ S3 เป็น external dependency และเข้ากับ SQLite ได้ดี
      ดูประสิทธิภาพ SQLite บน ZeroFS
  • มี implementation ไว้แล้วใน SQLite driver สำหรับ Go
    โค้ดตัวอย่าง ncruces/go-sqlite3
    ควบคุมผ่าน โค้ดโปรแกรมได้เลยโดยไม่ต้องใช้ environment variable และจัดการหลาย DB พร้อมกันได้
    แต่ PRAGMA litestream_time จะมีผล ในระดับ connection ดังนั้นถ้าใช้ connection pool ต้องระวัง
    • พอเห็น .load litestream.so ก็ทำให้นึกถึง ncruces/go-sqlite3 ขึ้นมาทันที
      สงสัยว่าการทำให้มันใช้ได้ในสภาพแวดล้อม wasm ยากไหม
  • ช่วงนี้กำลังเรียนรู้ DuckDB และเริ่มเห็นความต่างกับ SQLite
    ส่วนขยาย “DuckLake” ของ DuckDB จะสร้าง snapshot ในทุกทรานแซ็กชันเพื่อให้ฟีเจอร์ “time travel”
    ซึ่งคล้ายกับ PITR ของ Litestream VFS
    ในโลก OLTP จะเรียกสิ่งนี้ว่าความสามารถด้านการกู้คืน ส่วนใน OLAP จะเรียกว่า “Time Travel”
    DuckLake ใช้ external catalog DB (PostgreSQL/MySQL/SQLite) เพื่อประสานการเข้าถึงแบบหลายโปรเซส
    ขณะที่ Litestream เปิดให้หลาย reader เข้าถึงพร้อมกันได้ผ่าน ไฟล์ LTX แบบ immutable บน S3
    ทั้งสองโลกกำลังมุ่งไปสู่โครงสร้างแบบ “shared storage + metadata + compaction” เหมือนกัน
    อยากให้มี การร่วมมือข้ามโปรเจกต์ แบบนี้มากขึ้น
  • ในฐานะคนรักแซนด์วิช ฉันอยากรู้มากว่าข้อมูล คะแนนแซนด์วิช นั้นเป็นอย่างไร
  • ฟังดูน่าสนใจ แต่ยังงงอยู่ว่าจริง ๆ แล้วมีการประกาศซอฟต์แวร์อะไรออกมาแน่ เป็น Litestream เวอร์ชันใหม่หรือ?
    • ผู้เขียนเอง ใช่แล้ว มีการปล่อย Litestream v0.5.3 ใหม่ และเพิ่ม ตัวเลือก VFS แบบอ่านอย่างเดียว เข้ามา
      บันทึกการออกรุ่น v0.5.3
    • เวอร์ชันนี้ยังมี รองรับการทำ directory replication สำหรับ DB แบบ multi-tenant ด้วย เป็นส่วนเสริมที่ดีมาก
  • สงสัยว่ามันทำงานร่วมกับ sqlite extension อื่น ๆ ได้ไหม
    เช่นถ้ากำลังใช้ส่วนขยายค้นหาเวกเตอร์อย่าง sqlite-vec หรือ vss อยู่
    จะสามารถแบ็กอัปขึ้น S3 แบบเรียลไทม์ด้วย Litestream และ query จากระยะไกลผ่าน Litestream VFS ได้หรือไม่
    • ฉันก็สงสัยเหมือนกัน ถ้า query รันในเครื่องโลคัลและ ดึงจาก S3 เป็นระดับ page ตามที่จำเป็น ก็น่าจะทำงานได้ตามปกติ
      คงต้องลองทดสอบดูเอง
    • ได้ (มีแค่นั้นเลย)