Comment le journal Delta Lake rend-il une table ACID ?

Questions d’entrevue Formats et stockage

Intermédiairedelta-lakeacidjournal

La réponse courte

Delta Lake n’invente pas un format de lignes. Les données sont des fichiers Parquet. Ce qui change, c’est un dossier _delta_log : une suite de commits (JSON, puis des checkpoints Parquet) qui dit, pour chaque version, quels fichiers font partie de la table, quelles statistiques ils portent, quel est le schéma.

Une écriture réussie, c’est ajouter un fichier de log atomiquement (souvent un put-if-absent de 0000N.json sur le stockage objet). Tant que ce commit n’existe pas, les nouveaux Parquet sont invisibles. Un job tué au milieu laisse des objets orphelins, pas une table à moitié vraie. Un lecteur qui a ouvert la version 41 continue de voir exactement les fichiers de la 41, même si la 42 se commite pendant ce temps : isolation d’instantané.

Les conflits d’écrivains se règlent en concurrence optimiste. Deux jobs lisent la version 41, écrivent leurs Parquet, tentent tous les deux la 42. Un seul gagne. L’autre recommence (ou échoue), éventuellement en relisant les fichiers touchés. Ce n’est pas un verrou de base : c’est un compare-and-swap sur le numéro de version.

Ce que « ACID » veut dire ici, sans marketing

  • Atomicité. Le commit est l’unité. Pas de « 14 fichiers sur 20 visibles ».
  • Cohérence. Le schéma et les contraintes déclarées sont vérifiés au commit (selon les réglages), pas après coup par le premier lecteur.
  • Isolation. Lecture sur un snapshot ; pas de dirty read d’une écriture en cours. Ce n’est pas le SERIALIZABLE d’Oracle sur toutes les transactions longues — ne survendez pas.
  • Durabilité. Une fois le JSON de log durable sur S3/ADLS, la version existe. Les Parquet doivent l’être avant le commit (ordre d’écriture : data, puis log).

Le checkpoint (tous les N commits) compacte l’historique du log pour que relire l’état courant ne force pas à rejouer 80 000 petits JSON.

Ce que l’intervieweur vérifie

Que vous situez Delta au-dessus du stockage objet, qui lui n’est pas ACID. S3 offre une création conditionnelle d’objet, pas des transactions multi-clés. Le journal simule la transaction en ne publiant la liste de fichiers qu’en une fois.

La relance : « un lecteur peut-il voir des fichiers que l’écrivain n’a pas encore commités ? » Non, s’il lit via Delta. Oui, s’il liste le préfixe s3://…/table/ à la main et ouvre tous les Parquet — y compris les orphelins. D’où : on ne lit plus une table Delta comme un dossier Hive.

Deuxième relance : « et deux tables d’un coup ? » Un commit = une table. Un crossing de deux lacs n’est pas une transaction distribuée. Pour ça, on orchestre (saga, two-phase métier) ou on accepte l’incohérence temporaire.

Le piège

Confondre ACID de table et qualité de données. Un MERGE parfaitement isolé peut très bien écrire des clés en double si votre jointure est fausse. Le journal garantit un état publié, pas un modèle métier juste.

Autre piège : laisser le log et les données sur des couches dont la cohérence de lecture est douteuse, ou vider les vieux JSON à la main. Sans protocole (VACUUM, rétention), vous cassez le time travel — ou pire, le protocol de lecture.

Toutes les questions Formats et stockage