2010-11-04 16 views
6

Ho un'applicazione multithread che utilizza SQLite (3.7.3)Evitare di database sqlite3 bloccato

Mi colpisce l'errore bloccato database che sembra essere abbastanza diffuso. Mi chiedo come evitarlo nel mio caso.

Lasciatemi descrivere cosa sto costruendo. Spiacente, nessun codice è troppo grande e complesso.

Ho circa 8 thread che accedono contemporaneamente al database. Ognuno di questi thread può leggere o scrivere allo stesso tempo.

Ogni riga di una tabella nel database ha un percorso file che punta a una risorsa + altri attributi relativi a tale risorsa.

3 campi di nota sono lettori, stato e del.

lettori viene incrementato ogni volta che un thread legge dalla risorsa, ma solo se lo stato> 0 e del = 0.

Così ho un po 'di SQL che fa

UPDATE resource set readers=readers+1 where id=? AND del=0 AND status>0 

Dopo di che, ho il check il numero di righe aggiornate. Dovrebbe essere solo 1. Dopo che provo a leggere la riga indietro con una selezione. Lo faccio anche se non è riuscito ad aggiornare perché ho bisogno di sapere il motivo per cui è fallito.

Ho provato a includere sia l'aggiornamento sia la selezione in una transazione, ma questo non ha aiutato. Ho controllato che sto chiamando finalize anche sulle mie dichiarazioni.

Ora, ho pensato che serializzazione SQLite per impostazione predefinita. Ho provato un paio di modalità aperte ma ho ancora lo stesso errore.

E prima che tu lo chieda, no non intendo andare su mysql. Ho assolutamente bisogno di zero config.

Qualcuno può fornire alcuni suggerimenti su come evitare questo tipo di problema? dovrei spostare i lettori bloccati dal DB? Se lo faccio, con quale meccanismo dovrei sostituirlo? Sto usando Linux in C++ e con la libreria boost disponibile.

MODIFICA: È interessante notare che l'aggiunta di COMMIT dopo la mia chiamata aggiornata ha migliorato notevolmente le cose.

+1

L'accettazione più frequente consente blocchi granulari ESCLUSIVI più dettagliati sul file di database, il che riduce il tempo di attesa dei lettori in attesa sul tavolo da sbloccare. Questo a spese del sovraccarico del file di giornale aumentato. Controlla http://sqlite.org/lockingv3.html#writing per maggiori informazioni. – checker

risposta

1

Quando si apre il db, è necessario configurare il 'timeout occupato'

int sqlite3_busy_timeout(sqlite3*, int ms); 

http://www.sqlite.org/c3ref/busy_timeout.html

+2

Ciao, sì, l'ho provato. Aiuta un po '. Ma anche quando lo si imposta fino a 1 secondo, si verifica ancora il problema di blocco. Ho attivato la modalità shared_cache e sembra essere più di un timeout occupato. Ho intenzione di provare entrambi. – Matt

+0

Risulta che sqlite è stato appena martellato troppo difficile per la mia app. Quindi ho spostato il campo dei lettori nella memoria. Ciò ha migliorato le prestazioni di circa il 10000% e sto colpendo meno l'hard disk. – Matt

1

Prima domanda: stai cercando di utilizzare una connessione con tutte le otto thread? In tal caso, assicurarsi che ogni thread abbia una propria connessione. Non conosco nessun database a cui piaccia.

controllare anche le FAQ: http://www.sqlite.org/faq.html

Apparentemente SQLite deve essere compilato con l'opzione SQLITE_THREADSAFE preprocessore impostato a 1. Hanno un metodo per determinare se questo è il vostro problema.

Un altro problema è che le scritture possono avvenire solo da un processo in modo sicuro.

+0

Sì, una connessione per thread. Controllerò l'opzione del preelaboratore thread-safe. Tuttavia, avevo l'impressione che fosse il default. – Matt

+0

Come ho impostato questa opzione? – ademar111190

Problemi correlati