2009-06-30 21 views
15

¿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

+0

Al menos podría haber etiquetado su pregunta con el lenguaje de programación apropiado. –

+0

Yeap, o especifique que necesita un enfoque agnóstico y agnóstico de agnóstico de todas las lenguas. – sharptooth

+1

Intentaría preguntar de nuevo sin "mostrar el código" ... –

Respuesta

13

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.

+0

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!?!? –

+0

@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

+1

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 –

2

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.

+1

Hmm, ¿SQLite no proporciona bloqueos para proteger el acceso al archivo de base de datos? –

0

El SQLite Preguntas sobre exactamente this

+1

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. –

+0

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 ... –

+0

https://meta.stackexchange.com/questions/225370/your-answer-is-in-another- castillo-cuando-es-una-respuesta-no-una-respuesta –

2

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.

Cuestiones relacionadas