Comprende el modelo de bloqueo de SQLite, sus transacciones y las anomalías de aislamiento descritas por el estándar SQL.
Abrir esta lección en KodokonSQLite bloquea a nivel del archivo de base de datos completo, no de la fila. En el modo por defecto (rollback journal), los lectores comparten un bloqueo SHARED, pero solo un escritor a la vez puede obtener el bloqueo EXCLUSIVE. Consecuencia: las escrituras se serializan. Creemos una tabla para trabajar con transacciones.
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;El bloqueo evoluciona por etapas: UNLOCKED, luego SHARED (lectura), RESERVED (intención de escribir), PENDING, y finalmente EXCLUSIVE (escritura). Si una transacción ya mantiene el bloqueo de escritura, otra recibe el error SQLITE_BUSY. En lugar de fallar de inmediato, define un tiempo de espera con busy_timeout, y activa el modo WAL para dejar que los lectores y el escritor avancen en paralelo.
-- A single writer, concurrent readers
PRAGMA journal_mode = WAL;
-- Wait up to 5 s if the database is busy
PRAGMA busy_timeout = 5000;El estándar SQL describe tres anomalías: la lectura sucia (leer datos no confirmados), la lectura no repetible (releer una fila y ver un valor diferente) y la lectura fantasma (repetir una consulta de rango y ver aparecer filas nuevas). Como SQLite serializa a los escritores, se comporta en la práctica como SERIALIZABLE: estas anomalías no aparecen (fuera del modo de caché compartida con read_uncommitted). En otros sistemas, eliges el nivel de forma explícita.
-- 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 y BEGIN IMMEDIATE?