9 poin oleh GN⁺ 2025-04-21 | 1 komentar | Bagikan ke WhatsApp
  • Tabel virtual SQLite juga mendukung penulisan dan transaksi, dengan mengimplementasikan hook seperti xUpdate, xSync, xCommit, dan xRollback
  • SQLite pada dasarnya menjamin atomisitas dengan skema rollback journal, dan saat menangani beberapa file DB, super-journal digunakan untuk mengoordinasikan commit secara keseluruhan
  • Tabel virtual juga termasuk dalam protokol transaksi SQLite, sehingga jika xSync gagal, seluruh transaksi akan di-rollback
  • Commit dibagi menjadi 2 tahap: xSync untuk pekerjaan yang bisa gagal, sedangkan xCommit sebaiknya hanya melakukan pembersihan sederhana
  • xCommit dan xRollback selalu bisa dipanggil, jadi keduanya harus ditulis sebagai fungsi pembersihan yang dapat berjalan tanpa gagal

Tabel Virtual dan Pemrosesan Transaksi di SQLite

Dalam artikel sebelumnya, diperkenalkan cara dasar mendaftarkan dan menjalankan query pada tabel virtual SQLite menggunakan bahasa Go. Artikel ini membahas cara mengimplementasikan tabel virtual yang dapat ditulisi dan mendukung transaksi.

Dukungan Penulisan dan Transaksi pada Tabel Virtual

  • Antarmuka tabel virtual SQLite bukan hanya baca-saja

  • Dengan mengimplementasikan hook xUpdate, penulisan ke sumber data eksternal juga dimungkinkan

  • Untuk konsistensi transaksi yang sesungguhnya, diperlukan hook transaksi berikut:

    • xBegin: pemberitahuan dimulainya transaksi
    • xSync: persiapan untuk commit dengan aman ke disk (jika gagal di sini, seluruh transaksi di-rollback)
    • xCommit: commit akhir dan pembersihan
    • xRollback: melakukan rollback jika transaksi dibatalkan
  • Bahkan saat dimodifikasi bersama tabel biasa atau tabel virtual lain, SQLite mengaitkan semua hook untuk menjamin atomisitas

Cara Kerja Internal Transaksi SQLite

Rollback Journal

  • Secara default, SQLite menyimpan halaman ke file cadangan (journal) sebelum menimpanya
  • Jika terjadi masalah, data dipulihkan dari journal untuk menjamin atomisitas

> Catatan: SQLite juga mendukung mode WAL, tetapi itu di luar cakupan artikel ini

Super-Journal

  • Saat beberapa database terhubung, sinkronisasi sulit dilakukan hanya dengan journal terpisah untuk tiap DB

  • Super-journal adalah file level lebih tinggi yang mengoordinasikan commit antar banyak file

  • Jika hanya menangani beberapa tabel virtual dalam satu file DB, sinkronisasi tetap bisa dilakukan tanpa super-journal

  • Dalam kasus apa pun, SQLite secara otomatis memanggil hook xSync, xCommit, dan xRollback dalam alur transaksi

Two-Phase Commit bersama Tabel Virtual

Proses commit di SQLite terdiri dari dua tahap:

Tahap 1: xSync (menjamin durability)

  • Semua halaman atau journal dari setiap B-Tree dan file DB disinkronkan dengan aman ke disk
  • Hook xSync juga dipanggil untuk masing-masing tabel virtual
  • Jika satu saja xSync gagal, seluruh transaksi akan di-rollback → atomisitas tetap terjaga

Tahap 2: pembersihan (xCommit)

  • Setelah penyimpanan ke disk selesai, file journal dihapus dan pembersihan tabel virtual dijalankan

  • Berikut cuplikan kode dari vdbeaux.c

    disable_simulated_io_errors();  
    sqlite3BeginBenignMalloc();  
    for(i=0; i<db->nDb; i++){  
      Btree *pBt = db->aDb[i].pBt;  
      if( pBt ){  
        sqlite3BtreeCommitPhaseTwo(pBt, 1);  
      }  
    }  
    sqlite3EndBenignMalloc();  
    enable_simulated_io_errors();  
    sqlite3VtabCommit(db);  
    
  • Di dalam sqlite3VtabCommit(), semua pemanggilan xCommit pada praktiknya diabaikan meskipun gagal → murni tahap pembersihan

    int sqlite3VtabCommit(sqlite3 *db){  
      callFinaliser(db, offsetof(sqlite3_module,xCommit));  
      return SQLITE_OK;  
    }  
    
  • Karena durability sudah dijamin oleh xSync, kegagalan pada xCommit dan xRollback akan diabaikan

Hal yang Perlu Diperhatikan Penulis Tabel Virtual

  • Pekerjaan yang bersifat persisten harus ditempatkan di xSync
    • Operasi yang bisa gagal seperti network I/O, penulisan file, dan sejenisnya harus ditangani di sini agar transaksi dapat dibatalkan dengan aman
  • xRollback tetap bisa dipanggil bahkan setelah xSync
    • Jika xSync dari tabel lain gagal, seluruh transaksi akan di-rollback
  • xCommit dan xRollback harus ditulis sebagai fungsi pembersihan yang tidak gagal
    • Harus idempoten, sehingga dipanggil berkali-kali pun tidak mengubah keadaan

Kesimpulan

  • Mekanisme journaling SQLite menjamin commit atomik untuk semua elemen, termasuk tabel biasa dan tabel virtual
  • Hook transaksi pada tabel virtual terintegrasi secara alami ke dalam alur transaksi SQLite
  • Pengembang yang mengimplementasikan tabel virtual harus berfokus pada xSync untuk menjaga integritas data, lalu memisahkan pekerjaan pembersihan ke xCommit dan xRollback

1 komentar

 
GN⁺ 2025-04-21
Komentar Hacker News
  • Senang melihat tulisan tentang vtab. Saya mengimplementasikan dukungan vtab saat mengerjakan reimplementasi SQLite dalam Rust, jadi belakangan ini saya belajar banyak tentang vtab. vtab sangat kuat dan mungkin belum dimanfaatkan sepenuhnya
  • Menarik. Namun, ini menggunakan paket go-sqlite3 milik mattn. Itu adalah CGO
    • Saya penasaran apakah ini merupakan persyaratan yang umum atau diharapkan dalam Go modern