sqlite.h


BEGIN TRANSACTION - COMMIT TRANSACTION - ROLLBACK TRANSACTION

Sintaxis BEGIN TRANSACTION
BEGIN TRANSACTION
Sintaxis COMMIT TRANSACTION
COMMIT TRANSACTION
Sintaxis ROLLBACK TRANSACTION
ROLLBACK TRANSACTION

No se pueden hacer modificaciones en una base de datos fuera de una transacción. Cualquier sentencia que modifique la base de datos (básicamente, cualquier sentencia SQL que no sea SELECT) comenzará utomáticamente una transacción si no hay una abierta ya. Las transacciones abiertas automaticamente se cierran cuando finaliza la última consulta.

Las transacciones se pueden empezar manualmente usando la sentencia BEGIN. Estas transacciones suelen persistir hasta la siguiente sentencia COMMIT o ROLLBACK. Pero una transacción también puede hacer un ROLLBACK si la base de datos se cierra o si se produce un error y se ha especificado ROLLBACK en el algoritmo de resolución de conflictos. Ver la documentación la cláusula adicional ON CONFLICT para información adicional sobre el algoritmo de resolución de conflictos.

END TRANSACTION es un sinónimo para COMMIT.

Las transacciones creadas usando BEGIN...COMMIT no pueden anidarse. Para crear transacciones anidadas hay que usar las sentencias SAVEPOINT y RELEASE. La cláusula "TO SAVEPOINT name" de la sentencia ROLLBACK mostrada en el diagrama de sintaxis anterior sólo se puede aplicar a transacciones SAVEPOINT. Un intento de invocar la sentencia BEGIN en el interior de una transacción fallará con un error, independientemente de si la transacción empezó con un SAVEPOINT o con un BEGIN anterior. Las sentencias COMMIT y ROLLBACK sin la cláusula TO funcionaná igual en transacciones SAVEPOINT que en transacciones que empiecen con BEGIN.

Las transacciones pueden ser diferidas, inmediatas o exclusivas. El comportamiento por defecto es diferido. Diferido significa que no se necesitan bloqueos en la base de datos hasta que se produzca el primer acceso. Así, con una transacción diferida, la sentencia BEGIN no hace nada con respecto al sistema de ficheros. Los bloqueos no son activados hasta la primera operación de lectura o escritura. La primera operación de lectura sobre la base de datos crea un bloqueo SHARED (compartido) y la primera operación de escritura crea un bloqueo RESERVED (reservado). Debido a que los bloqueos se difieren hasta que son necesarios, es posible que otro proceso o hilo pueda crear una transacción y escribir en la base de datos después de que se haya ejecutado el BEGIN en el hilo actual. Si la transacción es inmediata, los bloqueos RESERVED se hacen en todas las bases de datos tan pronto como se ejecuta la sentencia BEGIN, sin esperar a que la base de datos sea usada. Después de un BEGIN IMMEDIATE, no será posible que otras conexiones escriban en la base de datos, ni que ejecuten un BEGIN IMMEDIATE o un BEGIN EXCLUSIVE. Sin embargo, otros procesos pueden continuar leyendo de la base de datos. Una transacción exclusiva crea bloqueos exclusivos sobre todas las bases de datos. Después de un BEGIN EXCLUSIVE, ninguna otra conexión de base de datos, excepto conexiones read_uncommitted, podrán hacer lecturas de la base de datos ni ninguna otra conexión, son excepción, podrá escribir en la base de datos hasta que la transacción se haya completado.

Una transacción implícita (aquella que comienza autimáticamente, no una que empiece con BEGIN) se completa automáticamente cuando la última sentencia activa finalice. Una sentencia finaliza cuando su preparación de sentencia se reinicia o finaliza. Una apertura de un sqlite3_blob usado para entradas y salidas incrementales BLOB cuenta como una sentencia inacabada. El sqlite3_blob finaliza cuando se cierra.

La sentencia COMMIT explícita se ejecuta inmediatamente, aunque existan sentecias SELECT pendientes. Sin embargo, si hay operaciones de escritura pendientes, la sentencia COMMIT fallará con un código de error SQLITE_BUSY.

Un intento de ejecutar COMMIT también puede producir un código de error SQLITE_BUSY si otro hilo o proceso tiene un bloqueo de lectura en la base de datos que impida que la base de datos sea actualizada. Cuando COMMIT falla de este modo, la transacción permanece activa y el COMMIT puede ser repetido más tarde después de que el proceso de lectura haya tenido la oportunidad de terminar.

El ROLLBACK puede fallar con un error SQLITE_BUSY si existe cualquier consulta pendiente. Tanto las consultas sólo de lectura o las de lectura/escritura pueden hacer que un ROLLBACK falle. Un ROLLBACK debe fallar si existen operaciones de lectura pendientes (al contrario que COMMIT que puede tener éxito) porque ocurrirán cosas malas si la imagen de la base de datos en memoria es modificada a partir de una consulta activa.

Si la variable de entorno PRAGMA journal_mode está asignada a OFF (por lo tanto se desactiva el archivo de rollback) entonce el comportamiento de la sentencia ROLLBACK queda indefinido.

Respuestas a errores en el interior de una transacción

Si ciertos tipos de errores ocurren durante una transacción, esta puede o no revertirse de forma automática. Los errores que producen este comportamiento incluyen:

  • SQLITE_FULL: la base de datos o el disco están llenos.
  • SQLITE_IOERR: error de I/O de disco.
  • SQLITE_BUSY: la base de datos está en uso por otro proceso.
  • SQLITE_NOMEM: falta memoria.
  • SQLITE_INTERRUPT: procesamiento interrumpido por una petición de la aplicación.

Para todos estos errores, SQLite intenta deshacer sólo la sentencia que estaba ejecutando y dejar sin cambios las sentencias anteriores dentro de la misma transacción, continuando con la misma transacción. Sin embargo, dependiendo de la sentencia que se esté evaluando y del punto en que se produzca el error, puede ser necesario que SQLite haga un rollback y cancele la transacción completa. Una aplicación puede indicar a SQLite el curso de acción mediate la función del API de C sqlite3_get_autocommit().

se recomienda que las aplicaciones respondan a los errores mostrados anteriormente mediante el envío de un comando ROLLBACK explícito. Si la transacción ya ha sido revertida automáticamente por la respuesta de error, el comando ROLLBACK fallará con un error, pero esto no causará ningún daño.

Versiones futuras de SQLite pueden extender la lista de errores que puedan causar un roolback de la transacción automático. También pueden cambiarse las respuestas a errores en el futuro. En particular, para simplificar el interfaz en futuras versiones de SQLite haciendo que los errores anteriores fuercen un rollback incondicional.