Guida basata su un intervento sistemistico concluso e verificato. Correzione verificata di lock SQLite: transazione lasciata aperta durante richieste HTTP e scritture concorrenti. Commit mirati, timeout e test.
Errore osservato
Un servizio Python che archiviava dati da più fonti iniziava a restituire sqlite3.OperationalError: database is locked. I processi effettuavano richieste HTTP durante l'ingestione e accedevano allo stesso file SQLite, con scritture concorrenti.
La causa
Una transazione aperta manteneva il lock durante operazioni di rete potenzialmente lente. Il timeout del client era breve e la seconda scrittura scadeva prima che la prima rilasciasse il lock.
Soluzione verificata
Abbiamo spostato il commit in modo che avvenisse dopo la scrittura di ciascuna fonte, evitando di mantenere transazioni durante le richieste HTTP. Abbiamo inoltre aumentato il timeout di attesa del database da 5 a 15 secondi. I test con scrittura concorrente e l'esecuzione successiva non hanno mostrato nuovi lock.
Schema Python
import sqlite3
def save_batch(db_path, records):
with sqlite3.connect(db_path, timeout=15) as con:
con.execute('PRAGMA busy_timeout = 15000')
con.executemany(
'INSERT INTO events (source, payload) VALUES (?, ?)',
records,
)
# Il context manager effettua il commit prima di uscire.
# La richiesta HTTP deve avvenire PRIMA di aprire la transazione.
payload = fetch_from_api()
save_batch('/percorso/app.db', payload)
Il codice è uno schema illustrativo, non una copia dell’applicazione. Le tabelle e le colonne devono essere adattate al proprio database.
Diagnosi e test
Misurare la durata delle transazioni e il numero di writer, controllare i timeout e riprodurre il carico con due processi indipendenti. Se si usa WAL, verificarne lo stato senza cancellare i file -wal o -shm quando il database è in uso.
Precauzioni
Aumentare soltanto il timeout spesso nasconde la causa. Per workload con numerose scritture, valutare una coda con un singolo writer o un database client-server. Prima delle modifiche conservare un backup coerente.
Risultato
Nel caso reale la revisione è stata salvata dopo backup, compilazione del codice e test concorrenti, con verifica successiva delle operazioni in produzione.
Guide correlate
I comandi con nomi segnaposto vanno adattati al proprio ambiente. Le configurazioni di produzione, gli IP e le credenziali non sono riportati.