Sérialisabilité et isolation des transactions

Cette page décrit la contention, la sérialisabilité et l'isolation des données transactionnelles. Pour obtenir des exemples de code transactionnel, consultez la page Transactions et écritures par lot.

Transactions et contention des données

Pour qu'une transaction aboutisse, les documents récupérés par ses opérations de lecture ne doivent pas être modifiés par les opérations en dehors de la transaction. Si une autre opération tente de modifier l'un de ces documents, elle entre en conflit avec la transaction.

Contention des données
Lorsqu'au moins deux opérations sont en concurrence pour contrôler le même document. Par exemple, une transaction peut nécessiter qu'un document reste cohérent lorsqu'une opération simultanée tente de mettre à jour les valeurs des champs de ce document.

Pour résoudre les conflits de données, Firestore retarde ou met en échec l'une des opérations. Les bibliothèques clientes Firestore relancent automatiquement les transactions ayant échoué en raison d'un conflit de données. Après un nombre défini de nouvelles tentatives, l'opération de transaction échoue et renvoie un message d'erreur :

ABORTED: Too much contention on these documents. Please try again.

Le comportement permettant de déterminer quelle opération différer ou mettre en échec dépend du type de bibliothèque cliente.

  • Les SDK pour mobile/Web utilisent des contrôles de simultanéité optimistes.

  • Les bibliothèques clientes de serveur utilisent des contrôles de simultanéité pessimistes.

Contention des données dans les SDK pour mobile/Web

Les SDK pour mobile/Web (iOS, Android, Web, C++) utilisent des contrôles de simultanéité optimistes pour résoudre les conflits de données.

Contrôles de simultanéité optimistes
D'après l'hypothèse que la contention de données est peu probable ou qu'il n'est pas efficace de maintenir le verrouillage des bases de données. Les transactions optimistes n'utilisent pas les verrous de base de données pour empêcher d'autres opérations de modifier les données.

Les SDK pour mobile/Web utilisent des contrôles de simultanéité optimistes, car ils peuvent fonctionner dans des environnements avec une latence élevée et une connexion réseau peu fiable. Le verrouillage de documents dans un environnement à latence élevée risque d'entraîner un trop grand nombre d'échecs en raison de conflits de données.

Dans les SDK pour mobile/Web, une transaction effectue le suivi de tous les documents lus au sein de la transaction. La transaction effectue ses opérations d'écriture seulement si aucun de ces documents n'a été modifié lors de son exécution. Si l'un des documents a été modifié, le gestionnaire de transactions relance la transaction. Si la transaction ne parvient pas à obtenir un résultat satisfaisant après quelques tentatives, elle échoue en raison d'un conflit de données.

Contention des données dans les bibliothèques clientes de serveur

Les bibliothèques clientes de serveur (C#, Go, Java, Node.js, PHP, Python, Ruby) utilisent des contrôles de simultanéité pessimistes pour résoudre les conflits de données.

Contrôles de simultanéité pessimistes
D'après l'hypothèse que la contention de données est probable. Les transactions pessimistes utilisent des verrous de base de données afin d'empêcher d'autres opérations de modifier les données.

Les bibliothèques clientes de serveur utilisent des contrôles de simultanéité pessimistes, car elles impliquent une latence faible et une connexion fiable à la base de données.

Dans les bibliothèques clientes de serveur, les transactions placent des verrous sur les documents qu'elles lisent. Le verrouillage d'une transaction sur un document empêche les autres transactions, écritures par lot et écritures non transactionnelles de modifier ce document. Une transaction déverrouille son document au moment du commit. Elle procède également au déverrouillage si elle dépasse le délai imparti ou échoue, quelle qu'en soit la raison.

Lorsqu'une transaction verrouille un document, les autres opérations d'écriture doivent attendre que la transaction le déverrouille. Les transactions obtiennent leurs verrous dans l'ordre chronologique.

Isolation sérialisable

La contention des données entre des transactions est étroitement liée aux niveaux d'isolation de la base de données. Le niveau d'isolation d'une base de données décrit la capacité du système à gérer les conflits entre des opérations simultanées. Les conflits proviennent des exigences de base de données suivantes :

  • Les transactions nécessitent des données précises et cohérentes.
  • Pour utiliser efficacement les ressources, les bases de données exécutent des opérations de manière simultanée.

Dans les systèmes dont le niveau d'isolation est faible, une opération de lecture dans une transaction peut lire des données inexactes provenant de modifications non validées dans une opération simultanée.

L'isolation sérialisable définit le niveau d'isolation le plus élevé. Par conséquent :

  • Vous pouvez partir du principe que la base de données exécute les transactions en série.
  • Les transactions ne sont pas affectées par les modifications non validées dans les opérations simultanées.

Cette garantie doit être appliquée, même lorsque la base de données exécute plusieurs transactions en parallèle. La base de données doit mettre en œuvre des contrôles de simultanéité pour résoudre les conflits susceptibles de compromettre cette garantie.

Firestore garantit une isolation sérialisable des transactions. Les transactions dans Firestore sont sérialisées et isolées par date de commit.

Isolation sérialisable par date de commit

Firestore attribue à chaque transaction une date de commit correspondant à un moment précis. Lorsque Firestore procède au commit des modifications d'une transaction sur la base de données, vous pouvez considérer que toutes les lectures et écritures de la transaction sont effectuées au moment précis du commit.

L'exécution réelle d'une transaction nécessite un certain temps. L'exécution d'une transaction commence avant la date du commit. Plusieurs opérations peuvent se chevaucher. Firestore assure l'isolation sérialisable et fournit les garanties suivantes :

  • Firestore procède au commit des transactions dans l'ordre, par date de commit.
  • Firestore isole les transactions des opérations simultanées et procède à leur commit ultérieurement.

En cas de contention des données entre des opérations simultanées, Firestore utilise des contrôles de simultanéité optimistes et pessimistes pour résoudre les conflits.

Isolation au sein d'une transaction

L'isolation de transaction s'applique également aux opérations d'écriture au sein d'une transaction. Les requêtes et les lectures d'une transaction n'affichent pas les résultats des écritures précédentes dans cette transaction. Même si vous modifiez ou supprimez un document au sein d'une transaction, toutes les lectures de cette transaction renvoient la version du document au moment du commit, avant ses opérations d'écriture. Les opérations de lecture ne renvoient aucun résultat si le document n'existait pas à ce moment-là.