9 पॉइंट द्वारा GN⁺ 2025-04-21 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • SQLite की virtual tables भी write और transaction support कर सकती हैं, और इसके लिए xUpdate, xSync, xCommit, xRollback जैसे hooks implement किए जाते हैं
  • SQLite डिफ़ॉल्ट रूप से rollback journal तरीके से atomicity सुनिश्चित करता है, और कई DB files के साथ काम करते समय super-journal से पूरे commit को coordinate करता है
  • Virtual tables भी SQLite के transaction protocol का हिस्सा होती हैं, इसलिए xSync fail होने पर पूरा transaction rollback हो जाता है
  • Commit दो चरणों में बंटा होता है, जहाँ xSync ऐसे कामों के लिए है जो fail हो सकते हैं, और xCommit को सिर्फ़ simple cleanup करना चाहिए
  • xCommit और xRollback कभी भी call किए जा सकते हैं, इसलिए इन्हें ऐसे cleanup functions की तरह लिखना चाहिए जो बिना fail हुए चलें

SQLite की virtual tables और transaction processing

पिछले लेख में Go भाषा के ज़रिए SQLite की virtual tables को register और query करने का बुनियादी तरीका बताया गया था। इस लेख में ऐसी virtual tables को implement करने का तरीका बताया गया है जो write कर सकती हैं और transaction support करती हैं.

Virtual table में write और transaction support

  • SQLite का virtual table interface सिर्फ़ read-only नहीं है

  • xUpdate hook implement करने पर external data source में भी write किया जा सकता है

  • सही transaction consistency के लिए ये transaction hooks चाहिए:

    • xBegin: transaction शुरू होने की सूचना
    • xSync: disk पर सुरक्षित commit की तैयारी (यहाँ fail होने पर पूरा rollback)
    • xCommit: final commit और cleanup
    • xRollback: transaction रुक जाने पर rollback
  • सामान्य tables या दूसरी virtual tables के साथ modify होने पर भी SQLite सभी hooks को जोड़कर atomicity सुनिश्चित करता है

SQLite transaction अंदरूनी तौर पर कैसे काम करता है

Rollback journal

  • SQLite डिफ़ॉल्ट रूप से pages को overwrite करने से पहले उन्हें backup file (journal) में सेव करता है
  • समस्या आने पर journal से recover करके atomicity सुनिश्चित की जाती है

ध्यान दें: SQLite WAL mode भी support करता है, लेकिन यह लेख उसके दायरे में नहीं है

Super-journal

  • जब कई databases जुड़े हों, तो हर DB के अलग journal से synchronization करना मुश्किल होता है

  • Super-journal नाम की higher-level file के ज़रिए कई files के बीच commit coordinate किया जाता है

  • अगर एक DB file के अंदर सिर्फ़ कई virtual tables ही हों, तो super-journal के बिना भी synchronization संभव है

  • किसी भी स्थिति में SQLite transaction flow के अंदर xSync, xCommit, xRollback hooks को अपने-आप call करता है

Virtual tables के साथ 2-phase commit

SQLite का commit process दो चरणों में होता है:

चरण 1: xSync (Durability सुनिश्चित करना)

  • सभी B-Tree और DB files के pages या journals को disk पर सुरक्षित रूप से sync किया जाता है
  • Virtual tables पर भी उनके xSync hooks call किए जाते हैं
  • अगर किसी एक xSync में failure हो जाए, तो पूरा transaction rollback हो जाता है → atomicity बनी रहती है

चरण 2: cleanup (xCommit)

  • Disk पर सेव पूरा हो जाने के बाद journal files delete की जाती हैं और virtual tables का cleanup किया जाता है

  • नीचे 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);  
    
  • sqlite3VtabCommit() के अंदर वास्तव में सभी xCommit calls fail हो जाएँ तब भी उन्हें ignore किया जाता है → यह पूरी तरह cleanup चरण है

    int sqlite3VtabCommit(sqlite3 *db){  
      callFinaliser(db, offsetof(sqlite3_module,xCommit));  
      return SQLITE_OK;  
    }  
    
  • क्योंकि durability xSync से पहले ही सुनिश्चित हो चुकी होती है, xCommit, xRollback fail हों तब भी उन्हें ignore किया जाता है

Virtual table लिखने वालों के लिए सावधानियाँ

  • Persistent काम हमेशा xSync में ही रखना चाहिए
    • Network I/O, file write जैसे fail हो सकने वाले काम यहीं होने चाहिए ताकि transaction सुरक्षित रूप से रुक सके
  • xSync के बाद भी xRollback call हो सकता है
    • अगर किसी दूसरी table का xSync fail हो जाए, तो पूरा rollback होगा
  • xCommit और xRollback को ऐसे cleanup functions की तरह लिखें जो fail न हों
    • इन्हें idempotent होना चाहिए, यानी कई बार call होने पर भी state न बदले

निष्कर्ष

  • SQLite का journaling mechanism base tables और virtual tables समेत सभी हिस्सों के लिए atomic commit सुनिश्चित करता है
  • Virtual tables के transaction hooks, SQLite transaction flow में स्वाभाविक रूप से integrate हो जाते हैं
  • Virtual table implement करने वाले developers को xSync पर ध्यान देकर data integrity सुनिश्चित करनी चाहिए, और cleanup work को xCommit, xRollback में बाँटना चाहिए

1 टिप्पणियां

 
GN⁺ 2025-04-21
Hacker News राय
  • vtabs पर यह लेख अच्छा लगा। मैंने Rust में SQLite को दोबारा implement करते हुए vtab support लागू किया था। इसलिए हाल ही में मैंने vtab के बारे में बहुत कुछ सीखा है। vtab बहुत शक्तिशाली हैं और शायद उनका पर्याप्त उपयोग नहीं होता
  • दिलचस्प। लेकिन यह mattn के go-sqlite3 package का उपयोग करता है। यह CGO है
    • सोच रहा हूँ कि आधुनिक Go में क्या यह एक सामान्य या अपेक्षित requirement है