2010-04-08 21 views
6

Estoy seguro de que me falta algo bastante obvio, pero no puedo dejar de ver mis secuencias de comandos pysqlite rompiendo con una base de datos está bloqueado error. Tengo dos scripts, uno para cargar datos en la base de datos, y otro para leer los datos, pero ambos se bloquean frecuente e instantáneamente dependiendo de lo que el otro esté haciendo con la base de datos en un momento dado. Tengo el tiempo de espera en los dos guiones se establece en 30 segundos:Python/SQLite - base de datos bloqueada a pesar de grandes tiempos de espera

cx = sqlite.connect("database.sql", timeout=30.0) 

Y creo que pueda ver alguna evidencia de los tiempos de espera en que consigo lo que parece ser un sello de tiempo (por ejemplo 0.12343827e-06 0,1 - y ¿cómo evito que se imprima?) arrojado ocasionalmente en el medio de la pantalla de salida formateada de Curses, pero ninguna demora que se acerque ni remotamente al tiempo de espera de 30 segundos, pero una de la otra sigue chocando una y otra vez. Estoy ejecutando RHEL 5.4 en un Blade IBM HS21 de 64 bits, y he escuchado algunas menciones sobre problemas relacionados con el multi-threading y no estoy seguro de si esto podría ser relevante. Los paquetes en uso son sqlite-3.3.6-5 y python-sqlite-1.1.7-1.2.1, y la actualización a versiones más nuevas fuera de las disposiciones oficiales de Red Hat no es una gran opción para mí. Posible, pero no deseable debido al ambiente en general.

He tenido autocommit=1 anteriormente en ambos scripts, pero desde entonces he inhabilitado en ambos, y ahora estoy cx.commit() ing en el script de inserción y no estoy comprometido en el script de selección. En última instancia, ya que solo tengo un guión haciendo modificaciones, realmente no veo por qué este bloqueo debería suceder. He notado que esto es significativamente peor con el tiempo cuando la base de datos se ha vuelto más grande. Recientemente fue de 13 MB con 3 tablas de igual tamaño, lo que equivale a aproximadamente 1 día de datos. Crear un nuevo archivo ha mejorado significativamente esto, lo que parece comprensible, pero el tiempo de espera en última instancia simplemente no parece ser obedecido.

Cualquier puntero muy apreciado.

EDITAR: desde que pregunté He podido reestructurar mi código ligeramente y usar una señal para escribir periódicamente entre 0 y 150 actualizaciones en una transacción cada 5 segundos. Esto ha reducido significativamente las apariciones del bloqueo, a menos de una por hora en lugar de una vez por minuto más o menos. Creo que podría ir más allá al asegurarme de que los tiempos en que escribo los datos se compensan unos segundos mientras leo datos en el otro guión, pero fundamentalmente estoy trabajando en un problema tal como lo percibo, haciendo que no se requiera un tiempo de espera, lo que no ocurre Parece correcto todavía. Ejército de reserva.

Respuesta

0

SQLite utiliza el bloqueo de la base de datos para cada escritura (actualización/inserción/eliminación/...). En mi humilde opinión, este bloqueo se mantiene hasta que finalice la transacción. Este es un bloqueo único que se lleva a cabo a través de subprocesos/procesos, AFAIK.

Por lo tanto, intentaría finalizar explícitamente tanto la transacción como la conexión para escribir el script y comprometerlo explícitamente incluso al leer el script y tratar de solucionar problemas de simultaneidad.

+0

¿Quiere cerrar la base de datos completa? Estoy bien con un bloqueo retenido, pero ninguno de los guiones está esperando el tiempo suficiente para que se libere el bloqueo. –

+0

Sí, me refiero a una conexión cercana a la base de datos desde la conexión que está haciendo escrituras. – Almad

+1

Bueno, estoy escribiendo en la base de datos cada pocos segundos, seguramente cerrarlo realmente no cambiará nada? Hay trabajos adicionales en la apertura y el cierre, entonces ¿eso no lo empeoraría? Y también si estoy comprometiendo los cambios antes de cerrar, entonces no hay ningún beneficio en cerrarlo de todos modos, ya que ya no estaría bloqueado. –

0

SQLite simplemente no está optimizado para cargas de trabajo pesadas en escritura, ni pretende serlo (pero no le importa escribir mucho en una transacción). Me parece que podría llegar al punto en que necesita cambiar a otra base de datos como MySQL, PostgreSQL, Oracle o DB2. Algunas de esas opciones son caras, pero para algunas cargas de trabajo eso es lo que necesita. (Tenga en cuenta también que las cargas de trabajo de escritura-pesados ​​tienden a ser mejor hacerlo con una solución de servidor de base de datos dedicado también, a pesar de que que empuja hacia arriba los costes de despliegue y complejidad. Algunas cosas simplemente cuestan.)

+0

Prefiero usar una base de datos adecuada, pero simplemente no está disponible por varias razones. –

+0

Bueno, entonces prepárate para que algunas cosas sean lentas. Simplemente no puede ser ayudado. –

2

En las primeras versiones de pysqlite , el parámetro timeout a sqlite.connect aparentemente se interpreta como milisegundos. Por lo tanto, su timeout=30.0 debe ser timeout=30000.

Cuestiones relacionadas