2010-11-04 18 views
6

Tengo una aplicación multiproceso que utiliza SQLite (3.7.3)Evitar la base de datos sqlite3 bloqueado

Estoy golpeando el bloqueo por error de base de datos que parece ser bastante frecuente. Me pregunto cómo evitarlo en mi caso.

Déjame describir lo que estoy construyendo. Lo sentimos, no hay código, es demasiado grande y complejo.

Tengo alrededor de 8 hilos que acceden simultáneamente a la base de datos. Cualquiera de esos hilos puede leer o escribir al mismo tiempo.

Cada fila en una tabla de la base de datos tiene una ruta de archivo que apunta a un recurso + otros atributos relacionados con ese recurso.

3 campos de nota son lectores, estado y del.

Los lectores se incrementa cada vez que un hilo lee desde el recurso, pero sólo si el estado> 0 y = 0. del

Así que tener un poco de SQL que hace

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

Después de eso, puedo comprobar la cantidad de filas actualizadas Solo debe ser 1. Después de eso trato de leer la fila de nuevo con un seleccionar. Lo hago incluso si falló para actualizar porque necesito saber el motivo por el cual falló.

Intenté ajustar tanto la actualización como la selección en una transacción, pero eso no ayudó. He comprobado que estoy llamando a finalizar mis declaraciones también.

Ahora, pensé que sqlite se serializa de manera predeterminada. He intentado un par de modos abiertos, pero sigo teniendo el mismo error.

Y antes de preguntar, no, no tengo la intención de ir a mysql. Necesito absolutamente ninguna configuración.

¿Puede alguien proporcionar algunos consejos sobre cómo evitar este tipo de problema? ¿Debo mover el bloqueo de los lectores del DB? Si lo hago, ¿con qué mecanismo debería reemplazarlo? Estoy usando Linux bajo C++ y con la biblioteca de impulso disponible.

EDITAR: Curiosamente, agregar COMMIT después de mi llamada actualizada mejoró las cosas dramáticamente.

+1

Commitir más a menudo permite bloqueos EXCLUSIVOS más granulares en el archivo de base de datos, lo que disminuirá el tiempo de espera de los lectores que esperan en la mesa para desbloquearse. Esto se produce a expensas de una mayor sobrecarga de archivos de diario. Visite http://sqlite.org/lockingv3.html#writing para obtener más información. – checker

Respuesta

1

Al abrir el DB, debe configurar el 'temporizador de ocupado'

int sqlite3_busy_timeout(sqlite3*, int ms); 

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

+2

Hola, sí lo intenté. Ayuda un poco Pero incluso cuando lo configura tan alto como 1 segundo, todavía se encuentra con el problema de bloqueo. He habilitado el modo shared_cache y eso parece ayudar más que el tiempo de espera ocupado. Voy a probar ambos. – Matt

+0

Resulta que SQLite acaba de ser muy difícil para mi aplicación. Así que he movido el campo de los lectores a la memoria. Esto ha mejorado el rendimiento alrededor del 10000% y estoy llegando al disco duro menos. – Matt

1

Primera pregunta: ¿está usted tratando de utilizar una conexión con todos los ocho hilos? Si es así, asegúrese de que cada hilo tenga su propia conexión. No sé de ninguna base de datos que le guste.

Además de revisar el FAQ: http://www.sqlite.org/faq.html

Al parecer SQLite tiene que ser compilado con una opción SQLITE_THREADSAFE preprocesador puesto a 1. Tienen un método para determinar si ese es su problema.

Otro problema es que las escrituras solo pueden suceder de un proceso de forma segura.

+0

Sí, una conexión por hilo. Comprobaré la opción del preprocesador de enhebrar hilos. Sin embargo, tenía la impresión de que era el valor predeterminado. – Matt

+0

¿Cómo configuro esta opción? – ademar111190

Cuestiones relacionadas