Transacciones y tablas virtuales en SQLite
(misfra.me)- Las tablas virtuales de SQLite también pueden admitir escritura y transacciones, usando hooks como
xUpdate,xSync,xCommityxRollback - SQLite garantiza la atomicidad con el modo de diario de rollback de forma predeterminada, y al manejar varios archivos de BD usa un super-journal para coordinar el commit completo
- Las tablas virtuales también forman parte del protocolo de transacciones de SQLite, y si
xSyncfalla se hace rollback de toda la transacción - El commit se divide en 2 fases:
xSyncpara trabajo que puede fallar, yxCommitsolo debe encargarse de tareas simples de limpieza xCommityxRollbacksiempre pueden ser llamados, por lo que deben implementarse como funciones de limpieza que puedan ejecutarse sin fallar
Tablas virtuales y manejo de transacciones en SQLite
En el artículo anterior se presentó la forma básica de registrar y consultar tablas virtuales de SQLite usando Go. En este artículo se explica cómo implementar tablas virtuales con soporte de escritura y transacciones.
Soporte de escritura y transacciones en tablas virtuales
-
La interfaz de tablas virtuales de SQLite no es solo de lectura
-
Si se implementa el hook
xUpdate, también se puede escribir en una fuente de datos externa -
Para una consistencia transaccional real, se necesitan los siguientes hooks de transacción:
xBegin: aviso de inicio de transacciónxSync: preparación para hacer commit seguro en disco (si falla aquí, se revierte toda la transacción)xCommit: commit final y limpiezaxRollback: ejecuta el rollback si la transacción fue abortada
-
Incluso cuando se modifican junto con tablas normales u otras tablas virtuales, SQLite coordina todos los hooks para garantizar la atomicidad
Cómo funcionan internamente las transacciones en SQLite
Diarios de rollback (Rollback Journals)
- SQLite, de forma predeterminada, guarda las páginas en un archivo de respaldo (journal) antes de sobrescribirlas
- Si ocurre un problema, se recupera desde el journal para garantizar la atomicidad
Nota: SQLite también soporta el modo WAL, pero queda fuera del alcance de este artículo
Super-journals
-
Cuando hay varias bases de datos conectadas, es difícil sincronizarlas usando solo journals individuales por cada BD
-
Se coordina el commit entre varios archivos mediante un archivo de nivel superior llamado super-journal
-
Si solo se manejan varias tablas virtuales dentro de un mismo archivo de BD, es posible sincronizarlas sin super-journal
-
En cualquier caso, SQLite llama automáticamente a los hooks
xSync,xCommityxRollbackdentro del flujo de la transacción
Commit en 2 fases con tablas virtuales
El proceso de commit en SQLite se realiza en dos fases:
Fase 1: xSync (garantiza la durabilidad)
- Sincroniza de forma segura en disco las páginas o journals de todos los B-Tree y archivos de BD
- También se llama al hook
xSyncde cada tabla virtual - Si falla cualquier
xSync, se hace rollback de toda la transacción → se conserva la atomicidad
Fase 2: limpieza (xCommit)
-
Una vez que el guardado en disco se completa, se eliminan los archivos de journal y se ejecuta la limpieza de las tablas virtuales
-
A continuación se muestra una parte del código de
vdbeaux.cdisable_simulated_io_errors(); sqlite3BeginBenignMalloc(); for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ sqlite3BtreeCommitPhaseTwo(pBt, 1); } } sqlite3EndBenignMalloc(); enable_simulated_io_errors(); sqlite3VtabCommit(db); -
Dentro de
sqlite3VtabCommit(), en la práctica se ignora incluso si fallan todas las llamadas axCommit→ es una fase puramente de limpiezaint sqlite3VtabCommit(sqlite3 *db){ callFinaliser(db, offsetof(sqlite3_module,xCommit)); return SQLITE_OK; } -
Como la durabilidad ya quedó asegurada con
xSync, sixCommitoxRollbackfallan, se ignoran
Puntos a tener en cuenta para autores de tablas virtuales
- Toda operación persistente debe ir obligatoriamente en
xSync- Trabajo que puede fallar, como I/O de red o escritura de archivos, debe hacerse aquí para que la transacción pueda abortarse de forma segura
- Incluso después de
xSync, puede llamarse axRollback- Si el
xSyncde otra tabla falla, se revierte toda la transacción
- Si el
xCommityxRollbackdeben implementarse como funciones de limpieza que no fallen- Deben ser idempotentes, es decir, no cambiar el estado aunque se llamen varias veces
Conclusión
- El mecanismo de journaling de SQLite garantiza commits atómicos para todos los elementos, incluidas las tablas normales y las virtuales
- Los hooks de transacción de las tablas virtuales se integran de forma natural en el flujo transaccional de SQLite
- Quien implemente tablas virtuales debe concentrarse en
xSyncpara asegurar la integridad de los datos y separar las tareas de limpieza enxCommityxRollback
1 comentarios
Comentarios en Hacker News