SQLite के लॉकिंग मॉडल, उसके ट्रांज़ैक्शन, और SQL मानक द्वारा वर्णित आइसोलेशन विसंगतियों को समझें।
इस पाठ को Kodokon में खोलेंSQLite पूरी डेटाबेस फ़ाइल के स्तर पर लॉक करता है, रो के स्तर पर नहीं। डिफ़ॉल्ट मोड (रोलबैक जर्नल) में, रीडर एक SHARED लॉक साझा करते हैं, लेकिन एक बार में केवल एक राइटर EXCLUSIVE लॉक प्राप्त कर सकता है। परिणाम: राइट क्रमबद्ध होते हैं। आइए ट्रांज़ैक्शन के साथ काम करने के लिए एक टेबल बनाएँ।
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
balance INTEGER NOT NULL
);
INSERT INTO accounts (id, balance)
VALUES (1, 100), (2, 50);
-- Read: deferred transaction (default)
BEGIN;
SELECT balance FROM accounts WHERE id = 1;
COMMIT;लॉक चरणों में विकसित होता है: UNLOCKED, फिर SHARED (पढ़ना), RESERVED (लिखने का इरादा), PENDING, और अंत में EXCLUSIVE (लिखना)। यदि कोई ट्रांज़ैक्शन पहले से राइट लॉक रखता है, तो दूसरे को SQLITE_BUSY त्रुटि मिलती है। तुरंत विफल होने के बजाय, busy_timeout से एक प्रतीक्षा विलंब सेट करें, और रीडरों तथा राइटर को समानांतर में आगे बढ़ने देने के लिए WAL मोड सक्षम करें।
-- A single writer, concurrent readers
PRAGMA journal_mode = WAL;
-- Wait up to 5 s if the database is busy
PRAGMA busy_timeout = 5000;SQL मानक तीन विसंगतियों का वर्णन करता है: डर्टी रीड (बिना कमिट किया गया डेटा पढ़ना), नॉन-रिपीटेबल रीड (किसी रो को दोबारा पढ़ना और एक भिन्न वैल्यू देखना), और फैंटम रीड (किसी रेंज क्वेरी को दोबारा चलाना और नई रो प्रकट होते देखना)। चूँकि SQLite राइटरों को क्रमबद्ध करता है, यह प्रभावी रूप से SERIALIZABLE की तरह व्यवहार करता है: ये विसंगतियाँ प्रकट नहीं होतीं (read_uncommitted के साथ शेयर्ड-कैश मोड को छोड़कर)। अन्यत्र, आप स्तर को स्पष्ट रूप से चुनते हैं।
-- Atomic transfer: immediate write lock
BEGIN IMMEDIATE;
UPDATE accounts
SET balance = balance - 10
WHERE id = 1;
UPDATE accounts
SET balance = balance + 10
WHERE id = 2;
COMMIT;BEGIN और BEGIN IMMEDIATE में क्या अंतर है?