Transactions et tables virtuelles dans SQLite
(misfra.me)- Les tables virtuelles SQLite peuvent aussi prendre en charge l’écriture et les transactions, en implémentant des hooks comme
xUpdate,xSync,xCommit,xRollback, etc. - SQLite garantit l’atomicité via le mécanisme de journal de rollback par défaut, et lorsqu’il manipule plusieurs fichiers de base de données, il coordonne le commit global avec un super-journal.
- Les tables virtuelles sont elles aussi intégrées au protocole de transaction de SQLite : si
xSyncéchoue, toute la transaction est annulée. - Le commit se décompose en deux étapes :
xSyncpour les opérations susceptibles d’échouer, puisxCommitqui ne doit faire qu’un simple travail de nettoyage. xCommitetxRollbackpouvant toujours être appelés, ils doivent être écrits comme des fonctions de nettoyage capables de s’exécuter sans échec.
Tables virtuelles et traitement des transactions dans SQLite
Dans un article précédent, les bases de l’enregistrement et de l’interrogation de tables virtuelles SQLite en Go étaient présentées. Cet article traite cette fois de la manière d’implémenter des tables virtuelles inscriptibles avec prise en charge des transactions.
Prise en charge de l’écriture et des transactions dans les tables virtuelles
-
L’interface des tables virtuelles de SQLite n’est pas en lecture seule
-
En implémentant le hook
xUpdate, il devient possible d’écrire aussi vers une source de données externe -
Pour obtenir une véritable cohérence transactionnelle, les hooks suivants sont nécessaires :
xBegin: notification de début de transactionxSync: préparation d’un commit sûr sur disque (si cela échoue ici, tout est annulé)xCommit: commit final et nettoyagexRollback: exécution du rollback si la transaction est interrompue
-
Même lorsque des modifications sont effectuées avec des tables ordinaires ou d’autres tables virtuelles, SQLite coordonne tous les hooks pour garantir l’atomicité
Fonctionnement interne des transactions SQLite
Journal de rollback (Rollback Journals)
- SQLite enregistre d’abord les pages dans un fichier de sauvegarde (journal) avant de les écraser
- En cas de problème, il restaure depuis le journal afin de garantir l’atomicité
> Remarque : SQLite prend aussi en charge le mode WAL, mais il n’entre pas dans le cadre de cet article
Super-journal (Super-Journals)
-
Lorsque plusieurs bases de données sont attachées, il est difficile de les synchroniser uniquement avec des journaux individuels pour chaque base
-
SQLite coordonne le commit entre plusieurs fichiers via un fichier de niveau supérieur appelé super-journal
-
Lorsqu’on ne manipule que plusieurs tables virtuelles dans un même fichier de base de données, la synchronisation reste possible sans super-journal
-
Dans tous les cas, SQLite appelle automatiquement les hooks
xSync,xCommitetxRollbackdans le flux transactionnel
Commit en deux phases avec les tables virtuelles
Le processus de commit de SQLite se déroule en deux phases :
Phase 1 : xSync (garantie de durabilité)
- Toutes les pages ou tous les journaux des B-Tree et des fichiers de base de données sont synchronisés de manière sûre sur disque
- Chaque table virtuelle voit également son hook
xSyncappelé - Si un seul
xSyncéchoue, toute la transaction est annulée → l’atomicité est préservée
Phase 2 : nettoyage (xCommit)
-
Une fois l’écriture sur disque terminée, le fichier journal est supprimé et le nettoyage des tables virtuelles est effectué
-
Voici un extrait du code 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); -
Dans
sqlite3VtabCommit(), tous les appels àxCommitsont en pratique ignorés même s’ils échouent : il s’agit d’une phase de nettoyage purint sqlite3VtabCommit(sqlite3 *db){ callFinaliser(db, offsetof(sqlite3_module,xCommit)); return SQLITE_OK; } -
Comme la durabilité a déjà été assurée par
xSync, les échecs dexCommitetxRollbacksont ignorés
Points d’attention pour les auteurs de tables virtuelles
- Les opérations persistantes doivent impérativement être placées dans
xSync- Les opérations susceptibles d’échouer, comme les E/S réseau ou l’écriture de fichiers, doivent être traitées ici afin que la transaction puisse être interrompue en toute sécurité
xRollbackpeut encore être appelé aprèsxSync- Si le
xSyncd’une autre table échoue, toute la transaction est annulée
- Si le
xCommitetxRollbackdoivent être écrits comme des fonctions de nettoyage qui n’échouent pas- Ils doivent être idempotents, c’est-à-dire ne pas modifier l’état même s’ils sont appelés plusieurs fois
Conclusion
- Le mécanisme de journalisation de SQLite garantit un commit atomique pour tous les éléments, y compris les tables ordinaires et les tables virtuelles
- Les hooks transactionnels des tables virtuelles sont naturellement intégrés au flux transactionnel de SQLite
- Les développeurs qui implémentent des tables virtuelles doivent se concentrer sur
xSyncpour garantir l’intégrité des données, puis répartir le travail de nettoyage entrexCommitetxRollback
1 commentaires
Commentaire Hacker News