android sqlite transactions ormlite

Android: niveles de aislamiento de transacciones SQLite(ORMLite)



transactions (2)

SQLite tiene 5 niveles diferentes de bloqueo: http://www.sqlite.org/lockingv3.html : desbloqueado, compartido, reservado, pendiente, exclusivo. El bloqueo importante para esta pregunta es el bloqueo compartido:

"COMPARTIDO: la base de datos puede leerse pero no escribirse. Cualquier cantidad de procesos puede contener bloqueos COMPARTIDOS al mismo tiempo, por lo tanto, puede haber muchos lectores simultáneos. Pero ningún otro hilo o proceso puede escribir en el archivo de base de datos mientras uno o más bloqueos COMPARTIDOS están activos. "

Los bloqueos son de nivel de tabla (de modo que mientras se hace algo con una sola fila en el DB, toda la tabla está bloqueada).

Por lo tanto, mientras selecciona datos, no se permite ningún otro proceso para alterar los datos. Los pasos de bloqueo para leer datos son: DESBLOQUEADO → PENDIENTE → COMPARTIDO → DESBLOQUEADO (puede ejecutar selecciones en una transacción). Entonces, una situación en la que está seleccionando algo y alguien alterará los datos no puede suceder.

Su pregunta es qué sucede si está actualizando la base de datos y selecciona en la misma tabla. En el modo de confirmación automática, el mecanismo de bloqueo para escritura / actualización es: DESBLOQUEADO → PENDIENTE → COMPARTIDO → RESERVADO → PENDIENTE → EXCLUSIVO → DESBLOQUEADO. Mientras está en el bloqueo exclusivo, no hay nuevos lectores (conexiones) que puedan conectarse a la base de datos. Solo un bloqueo EXCLUSIVO puede existir a la vez. SQLite esperará hasta que todos los demás bloqueos PENDIENTES de las conexiones de lectura se liberen y evitará cualquier nuevo. En este momento, comenzará a escribir los datos.

Por lo tanto, mi respuesta sería: siempre que el proceso de actualización no haya finalizado, su otro proceso obtendrá datos antiguos, por supuesto. Asegúrese de ejecutar la actualización en una transacción, de modo que no se produzcan incoherencias en los datos. SQLite cumple con ACID, por lo que una situación en la que se actualice parcialmente y se realicen incosistencias de datos no debería ocurrir.

Un gran libro sobre esto es "La guía definitiva de SQLite", especialmente el capítulo Transacciones.

Estoy usando ORMLite en mi proyecto de Android. Sé que Sqlite se ocupa del bloqueo del nivel de archivos. Muchos hilos pueden leer, uno puede escribir. Los bloqueos previenen más de una escritura. ¿Podría alguien explicar por favor qué sucederá en caso de que un hilo esté actualizando algún registro y otro hilo esté tratando de leer este registro? ¿El hilo (que intenta leer) obtiene datos desactualizados? ¿O estará bloqueado hasta que el primer hilo complete su operación de escritura? Como sé, hay 4 niveles de aislamiento de transacción: serializable, lectura repetible, lectura confirmada, lectura no confirmada. ¿Y hay alguna forma de cambiarlo en SQLite u ORMLite?


SQLite admite un par de niveles de aislamiento diferentes que se pueden seleccionar en tiempo de compilación y tiempo de ejecución.

http://www.sqlite.org/threadsafe.html

Supongo que el SQLite de Android está en modo Serialized de forma predeterminada. En términos de acceso de subprocesos múltiples, sí lo hace el bloqueo de lectura / escritura en el nivel del sistema de archivos para permitir múltiples lectores, pero solo un escritor a la vez:

http://www.sqlite.org/faq.html#q5

Sin embargo, ORMLite recomienda mucho y se esfuerza por mantener una única conexión a la base de datos, por lo que los problemas de bloqueo pueden no ser relevantes.

Más específicamente, si un hilo está actualizando el registro y otra lectura de hilo, entonces es una condición de carrera. O el hilo de lectura obtendrá el registro antes de la actualización o después de que se haya completado la actualización. Sin embargo, el lector no obtendrá datos parcialmente actualizados. Pero sospecho que lo sabías.

En términos de niveles de aislamiento admitidos por SQLite, el valor predeterminado es Serialized como se mencionó, pero parece que admite lectura no comprometida, al menos hasta cierto punto.

http://www.sqlite.org/sharedcache.html

Puede usar el método Dao.executeRaw () de ORMLite para habilitarlo:

dao.executeRaw("PRAGMA read_uncommitted = True;");

Sin embargo, no tengo ninguna experiencia con esto ni estoy seguro si le dará una vista consistente de la fila que se actualizó si se accede a ella varias veces en la misma consulta. Puede tener más que ver con vistas consistentes durante las transacciones de escritura.

Después de leer esta pregunta similar , no estoy seguro de que se pueda garantizar la misma vista de una fila en una tabla si se accede a ella varias veces en la misma consulta.