Come si dovrebbe garantire la correttezza quando più processi accedono a un singolo file di database SQLite?SQLite3 e più processi
risposta
Innanzitutto, evitare l'accesso simultaneo ai file di database sqlite. La concorrenza è uno dei punti deboli di sqlite e se si dispone di un'applicazione molto concorrente, prendere in considerazione l'utilizzo di un altro motore di database.
Se non è possibile evitare la concorrenza o far cadere SQLite, avvolgere il vostro scrittura transazioni in BEGIN IMMEDIATE;
... END;
. La modalità di transazione predefinita in sqlite è DEFERRED
, il che significa che un blocco viene acquisito solo al primo tentativo di scrittura effettivo. Con le transazioni IMMEDIATE
, il blocco viene acquisito immediatamente oppure ottieni immediatamente SQLITE_BUSY
. Quando qualcuno tiene un blocco nel database, altri tentativi di blocco comporteranno SQLITE_BUSY
.
Affrontare SQLITE_BUSY
è qualcosa che devi decidere per te. Per molte applicazioni, in attesa di un secondo o due e poi riprovare funziona abbastanza bene, rinunciando dopo i tentativi falliti n
. Ci sono gli helper API sqlite3 che rendono questo facile, ad es. sqlite3_busy_handler()
e sqlite3_busy_timeout()
ma può essere eseguito anche manualmente.
È anche possibile utilizzare la sincronizzazione a livello di sistema operativo per acquisire un blocco mutex nel database oppure utilizzare la messaggistica inter-thread/inter-processo a livello di sistema operativo per segnalare quando un thread ha terminato l'accesso al database.
So che uno deve utilizzare le transazioni in un unico processo. Tuttavia, la mia situazione è che ho più processi, al contrario di più thread, che accedono allo stesso DB contemporaneamente. Le transazioni SQLite gestiscono realmente tale concorrenza!?!? –
@Tom: Sì, nel livello di porting specifico per il sistema operativo sqlite3 esiste una funzionalità per il blocco che funziona attraverso i processi. Vedere http://www.sqlite.org/lockingv3.html per ulteriori informazioni – laalto
DEFERRED significa effettivamente che il database non è (condiviso) bloccato finché non vi si accede da una lettura o da una scrittura dopo l'istruzione BEGIN (sì, dovrebbe bloccarsi leggere). IMMEDIATE significa che il database è bloccato immediatamente dopo l'esecuzione di "INIZIA IMMEDIATA TRANSAZIONE". Vedi http://www.sqlite.org/lang_transaction.html –
Qualsiasi primitiva SQLite restituirà SQLITE_BUSY se tenta di accedere a un altro database che accede contemporaneamente. È possibile verificare il codice di errore e ripetere l'azione.
In alternativa è possibile utilizzare la sincronizzazione del sistema operativo - mutex su MS Windows o qualcosa di simile su altri sistemi operativi. Il processo proverà ad acquisire il mutex e se qualcuno lo detiene già, il processo verrà bloccato fino a quando l'altro processo non avrà completato l'operazione e rilascerà il mutex. Bisogna fare attenzione per evitare casi in cui il processo acquisisce il mutext e quindi non lo rilascia mai.
Hmm, SQLite non fornisce i blocchi per proteggere l'accesso ai file del database ?? –
Lo SQLite FAQ circa esattamente this
Ho letto le FAQ prima di pubblicare la mia domanda qui. Ovviamente avrei dovuto dirlo (questa era la lezione numero due che ho imparato oggi). Non riuscivo a vedere esattamente cosa volessero dire. Devo gestire tutte le operazioni di blocco da solo o SQLite supporta questo? "Quando qualsiasi processo vuole scrivere, deve bloccare l'intero file del database per la durata del suo aggiornamento, ma normalmente ci vogliono solo pochi millisecondi, altri processi aspettano solo che lo scrittore finisca e poi proseguono sulla loro attività". Ci vorrebbe qualche sforzo per implementare questo per me stesso. –
Non solo è noioso, è anche soggetto a errori. E spero che SQLite abbia il supporto necessario, nel qual caso mi chiedo quali funzioni dovrei usare. Come nota a margine, penso che la documentazione di SQLite sia un po 'troppo contenuta quando si tratta di esempi con codice sorgente ... –
https://meta.stackexchange.com/questions/225370/your-answer-is-in-another- castello-quando-è-una-risposta-non-an-risposta –
Fondamentalmente è necessario avvolgere il vostro codice di accesso ai dati con le transazioni. Ciò manterrà i tuoi dati coerenti. Nient'altro è richiesto.
In SQLite si utilizza
iniziare la transazione
COMMIT TRANSACTION
coppie per delimitare le transazioni. Metti il tuo codice SQL in mezzo per farlo eseguire in una singola transazione.
Tuttavia, come le persone precedenti hanno commentato prima di me, è necessario prestare molta attenzione ai problemi di concorrenza. SQLite può funzionare abbastanza velocemente se utilizzato per l'accesso in lettura (più lettori non sono bloccati e possono essere eseguiti contemporaneamente).
Tuttavia, l'immagine cambia considerevolmente se il codice intercala l'accesso in scrittura e in lettura. Con SQLite, l'intero file del database verrà bloccato anche se è attivo un singolo writer.
- 1. Come utilizzare lo stesso database SQLite3 da più processi Perl?
- 2. KyotoCabinet e più processi?
- 3. Scrittura simultanea con sqlite3
- 4. file su più processi
- 5. sqlite3.dll e system.data.sqlite.dll
- 6. Otto/EventBus tra più processi
- 7. Multiprocessing: più processi di cpu.count
- 8. sqlite3 seleziona da più tabelle "dove" roba
- 9. Crea connessione DB e mantiene su più processi (multiprocessing)
- 10. Come posso dividere e ricongiungere STDOUT da più processi?
- 11. GPUImageMovie utilizza più immagini come trame e processi
- 12. Stato sessione ASP.NET e più processi di lavoro
- 13. Registrazione di Python da più processi
- 14. condivisione puntatori tra più processi a forcella
- 15. sqlite3 preparazione, rilegatura e reseting statments
- 16. Più sessioni/processi WebBrower in una finestra
- 17. Problema forking fork() più processi Unix
- 18. Più memoria di processi .NET. Footprint
- 19. fork() processi figlio e genitore
- 20. sqlite3 e fmdb nested FMResultSet è possibile?
- 21. comando sqlite3 shell '.backup' e transazione
- 22. sola lettura accesso solo per sqlite3 da più thread
- 23. più istruzioni SQL in QSqlQuery che utilizzano il driver sqlite3
- 24. sqlite3 command-line - Come mostrare meno/più output
- 25. sqlite3 influiscono sulle prestazioni?
- 26. processi server multipli utilizzando nginx e uWSGI
- 27. Python Qual è la differenza tra un pool di processi di lavoro e l'esecuzione di più processi?
- 28. Qual è il metodo più semplice di comunicazione tra processi tra 2 processi C#?
- 29. fork() e wait() con due processi figlio
- 30. Memoria condivisa tra processi C++ e Java
Almeno avresti potuto taggare la tua domanda con il linguaggio di programmazione appropriato. –
Yeap o specifica che è necessario un approccio agnostico indipendente dalla piattaforma indipendente dalla lingua. – sharptooth
Vorrei provare a chiedere di nuovo senza "mostrami il codice" ... –