¿Cómo se debe garantizar la corrección cuando múltiples procesos acceden a un único archivo de base de datos SQLite?SQLite3 y procesos múltiples
Respuesta
Primero, evite el acceso simultáneo a los archivos de la base de datos sqlite. La concurrencia es uno de los puntos débiles de sqlite y si tiene una aplicación altamente concurrente, considere usar otro motor de base de datos.
Si no puede evitar la concurrencia o dejar sqlite, envuelva su escritura transacciones en BEGIN IMMEDIATE;
... END;
. El modo de transacción predeterminado en sqlite es DEFERRED
, lo que significa que se adquiere un bloqueo solo en el primer intento de escritura real. Con las transacciones IMMEDIATE
, el bloqueo se adquiere inmediatamente, o usted obtiene SQLITE_BUSY
inmediatamente. Cuando alguien mantiene un bloqueo en la base de datos, otros intentos de bloqueo darán como resultado SQLITE_BUSY
.
Tratar con SQLITE_BUSY
es algo que tiene que decidir por sí mismo. Para muchas aplicaciones, esperar uno o dos segundos y luego reintentar funciona bastante bien, renunciando después de n
intentos fallidos. Hay ayudantes API sqlite3 que hacen esto fácil, p. sqlite3_busy_handler()
y sqlite3_busy_timeout()
pero también se puede hacer manualmente.
También puede usar la sincronización de nivel de sistema operativo para adquirir un bloqueo de exclusión mutua en la base de datos o usar mensajes entre hilos/entre procesos a nivel de sistema para señalar cuando un hilo termina de acceder a la base de datos.
Sé que uno debe usar transacciones dentro de un proceso. Sin embargo, mi situación es que tengo múltiples procesos, en contraste con múltiples hilos, accediendo al mismo DB al mismo tiempo. ¿Las transacciones de SQLite realmente manejan tal concurrencia!?!? –
@Tom: Sí, en la capa de puertos específicos del sistema operativo sqlite3 hay una funcionalidad para el bloqueo que funciona en todos los procesos. Consulte http://www.sqlite.org/lockingv3.html para obtener más – laalto
DIFERIDO en realidad significa que la base de datos no está (compartida) bloqueada hasta que se acceda mediante una lectura o escritura después de la instrucción BEGIN (sí, debe bloquearse en el leer). INMEDIATO significa que la base de datos se bloquea inmediatamente después de ejecutar "COMENZAR TRANSACCIÓN INMEDIATA". Ver http://www.sqlite.org/lang_transaction.html –
Cualquier primitiva SQLite devolverá SQLITE_BUSY si intenta acceder a una base de datos a la que otro proceso está accediendo al mismo tiempo. Puede verificar ese código de error y simplemente repetir la acción.
Alternativamente, podría utilizar la sincronización del sistema operativo - mutex en MS Windows o algo similar en otros sistemas operativos. El proceso intentará adquirir el mutex y si alguien más lo tiene, el proceso se bloqueará hasta que el otro proceso finalice la operación y libere el mutex. Se debe tener cuidado para evitar casos cuando el proceso adquiere el texto alternativo y luego nunca lo libera.
Hmm, ¿SQLite no proporciona bloqueos para proteger el acceso al archivo de base de datos? –
El SQLite Preguntas sobre exactamente this
He leído las preguntas frecuentes antes de publicar mi pregunta aquí. Debería haber dicho eso (esta fue la lección número dos que aprendí hoy). No pude ver exactamente lo que significaban. ¿Se supone que debo manejar todas las cosas de bloqueo, o SQLite tiene soporte para eso? "Cuando un proceso desea escribir, debe bloquear todo el archivo de la base de datos mientras dure su actualización. Pero eso normalmente solo lleva unos pocos milisegundos. Otros procesos simplemente esperan que el escritor termine y luego continúan con sus actividades". Me tomaría un esfuerzo implementar esto por mí mismo. –
No solo es tedioso, también es propenso a errores. Y espero que SQLite tenga el soporte necesario, en cuyo caso me pregunto qué funciones se supone que debo usar. Como nota al margen, creo que la documentación de SQLite es un poco restringida cuando se trata de ejemplos con código fuente ... –
https://meta.stackexchange.com/questions/225370/your-answer-is-in-another- castillo-cuando-es-una-respuesta-no-una-respuesta –
Básicamente lo que necesita para envolver el código de acceso a datos con las transacciones. Esto mantendrá sus datos consistentes. No se requiere nada más.
En SQLite está utilizando
iniciar la transacción
COMMIT TRANSACTION
pares para delimitar sus transacciones. Coloque su código SQL en medio para que se ejecute en una sola transacción.
Sin embargo, como personas anteriores han comentado antes que yo, debe prestar mucha atención a los problemas de simultaneidad. SQLite puede funcionar razonablemente rápido si se usa para acceso de lectura (múltiples lectores no están bloqueados y pueden ejecutarse al mismo tiempo).
Sin embargo, la imagen cambia considerablemente si el código intercala el acceso de escritura y lectura. Con SQLite, todo el archivo de la base de datos se bloqueará si hay un solo escritor activo.
- 1. KyotoCabina y múltiples procesos?
- 2. fork() - múltiples procesos y llamadas al sistema
- 3. archivos en procesos múltiples
- 4. ¿Cómo usar la misma base de datos SQLite3 de múltiples procesos Perl?
- 5. Patrones para procesos múltiples PHP?
- 6. Registro Python desde procesos múltiples
- 7. ASP.NET estado de sesión y múltiples procesos de trabajo
- 8. sqlite3.dll y system.data.sqlite.dll
- 9. sqlite3 y cursor.description
- 10. Tramas múltiples de Python/procesos múltiples para leer puertos serie
- 11. Múltiples hilos o procesos con hilos
- 12. Múltiples procesos accediendo al mismo archivo
- 13. nginx: ¿Es multiproceso pero utiliza múltiples procesos?
- 14. Shell script para ejecutar procesos múltiples
- 15. Procesos de bifurcación/múltiples roscas | Bash
- 16. Problema al horquillar fork() múltiples procesos Unix
- 17. SQLite3 FTS4, MATCH y Android
- 18. Tuberías y procesos
- 19. sentencias SQL múltiples en QSqlQuery con el controlador sqlite3
- 20. cómo matar procesos y procesos secundarios de python?
- 21. Procesamiento de un solo archivo desde procesos múltiples en python
- 22. Multiproceso de Python: ¿cómo comparto un dict entre múltiples procesos?
- 23. fork() procesos secundarios y secundarios
- 24. TransactionScope en AppDomains y procesos
- 25. Compartiendo un puerto entre múltiples procesos node.js HTTP
- 26. ¿Cómo publico múltiples aplicaciones/procesos con un solo clic?
- 27. Múltiples sesiones/procesos de WebBrower en una ventana
- 28. Ejecución concurrente del kernel GPU desde procesos múltiples
- 29. SQLite3 y limitando el número de resultados
- 30. Implementar RoR en Heroku y Sqlite3 falla
Al menos podría haber etiquetado su pregunta con el lenguaje de programación apropiado. –
Yeap, o especifique que necesita un enfoque agnóstico y agnóstico de agnóstico de todas las lenguas. – sharptooth
Intentaría preguntar de nuevo sin "mostrar el código" ... –