Aller au contenu principal

Niveaux d'isolation (WriteSerializable et Serializable)

Delta Lake sur Databricks prend en charge deux niveaux d'isolation qui contrôlent la manière dont les opérations simultanées sur une table donnée interagissent :

Niveau d'isolation

Description

Sérialisable

Le niveau d'isolation le plus fort. Garantit que les opérations d'écriture validées et toutes les lectures sont sérialisables. Les opérations sont autorisées tant qu’il existe une séquence en série qui, lorsqu'elle est exécutée une par une, génère le même résultat que celui observé dans le tableau. Pour les opérations d'écriture, cette séquence sérielle est la même que l'ordre observé dans l'historique de la table.

WriteSerializable (default)

Un niveau d'isolation plus faible que Serializable. Garantit que seules les opérations d'écriture (et non les lectures) sont sérialisables. C'est toujours plus fort que l'isolation Snapshot. Offre un bon équilibre entre cohérence des données et disponibilité pour la plupart des opérations courantes.

Niveau d'isolation

Description

Sérialisable

Le niveau d'isolation le plus fort. Garantit que les opérations d'écriture validées et toutes les lectures sont sérialisables. Les opérations sont autorisées tant qu’il existe une séquence en série qui, lorsqu'elle est exécutée une par une, génère le même résultat que celui observé dans le tableau. Pour les opérations d'écriture, cette séquence sérielle est la même que l'ordre observé dans l'historique de la table.

WriteSerializable (default)

Un niveau d'isolation plus faible que Serializable. Garantit que seules les opérations d'écriture (et non les lectures) sont sérialisables. C'est toujours plus fort que l'isolation Snapshot. Offre un bon équilibre entre cohérence des données et disponibilité pour la plupart des opérations courantes.

Quand modifier le niveau d’isolation​

Conservez le niveau d'isolation default WriteSerializable pour la plupart des charges de travail.

Avec WriteSerializable, un DELETE, UPDATE ou MERGE qui start avant une insertion simultanée peut toujours commit après. Les lignes de l'insertion ne sont pas affectées, même si elles correspondent à la condition de l'opération. L'historique de la table affiche toujours l'insertion en premier, donc le contenu de la table ne correspond pas au résultat de la relecture des commits dans l'ordre de l'historique. Voir Exemple : suppression et insertion simultanées.

Passez la table en mode sérialisable si votre workload ne peut pas accepter ce résultat. Par exemple, si un DELETE doit supprimer chaque ligne correspondante existante lorsqu’il effectue un commit, ou si des processus en aval reconstruisent le contenu de la table à partir de l’ordre de commit dans l’historique. Avec Serializable, l’opération suivante échoue en raison d’un conflit et vous devez réessayer.

La sérialisation réduit le throughput pour les écritures simultanées. Les ajouts qui ne lisent pas la table ne sont jamais en conflit avec WriteSerializable, mais peuvent l'être avec Serializable. Voir Simultanéité au niveau des lignes.

Comment les niveaux d'isolation affectent les lectures​

Les opérations de lecture utilisent toujours l’isolation des instantanés. Le niveau d'isolation des écritures détermine si un lecteur peut voir un instantané d'une table qui, selon l'historique, « n'a jamais existé. »

  • **Sérialisable** : Un lecteur ne voit toujours que les tables qui sont conformes à l'historique.
  • **WriteSerializable** : un lecteur peut voir un état de table qui n'existe pas dans le log Delta

Exemple : Suppression et insertion simultanées​

Considérez un scénario où une transaction de suppression de longue durée et une transaction d'insertion start en même temps et lisent la version v0. La transaction d'insertion effectue un commit en premier et crée la version v1. Après cela, la transaction de suppression tente de commit v2:

t0: deleteTxn_START
t1: insertTxn_START
t2: insertTxn_COMMIT(v1)
t3: deleteTxn_COMMIT(v2)

Dans ce scénario, deleteTxn n'a pas vu les données insérées par insertTxn et ne les a pas supprimées :

  • Serializable : deleteTxn n'est pas autorisé à commit, et un conflit se produit
  • WriteSerializable : deleteTxn est autorisé à commit car les transactions peuvent être ordonnées. L'état de la table résultante est comme si insertTxn s'était produit après deleteTxn, de sorte que les lignes insérées font partie de la table. Cependant, l'historique Delta indique l'ordre de commit physique (insertTxn à la version v1 avant deleteTxn à la version v2).

Définir le niveau d'isolation​

Pour définir le niveau d'isolement, utilisez la commande ALTER TABLE :

SQL
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = <level-name>)

Où <level-name> est Serializable ou WriteSerializable.

Exemple :

SQL
-- Change from default WriteSerializable to Serializable
ALTER TABLE my_table SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

Quand Delta Lake commit-il sans lire la table?​

Les opérations INSERT ou append de Delta Lake ne lisent pas l'état de la table avant de effectuer un commit si les conditions suivantes sont remplies :

  1. La logique s'exprime à l'aide de la logique SQL INSERT ou en mode d'ajout.
  2. La logique ne contient ni sous-requêtes ni conditions qui référencent la table ciblée par l'opération d'écriture.

Comme pour les autres commits, Delta Lake utilise les métadonnées du log de transactions pour valider et résoudre les versions de table lors du commit, mais aucune version de la table n'est réellement lue.

remarque

De nombreux modèles courants utilisent des opérations MERGE pour insérer des données en fonction des conditions de la table. Bien qu'il soit possible de réécrire cette logique à l'aide d'instructions INSERT, si une expression conditionnelle fait référence à une colonne dans la table cible, ces instructions ont les mêmes limitations de concurrence que MERGE.

Ressources supplémentaires​