🎯 Objectif
Quand tu fais un dbt run
avec un modèle incremental, tu veux :
- insérer ou mettre à jour uniquement les nouvelles données,
- mais ne jamais laisser de demi-mise-à-jour si une erreur survient,
- idéalement, revenir à un état sain si une partie échoue.
✅ La gestion de transactions avec savepoints est la solution.
🧠 Pourquoi c’est important ?
Imaginons :
- ton modèle incrémental traite 1 million de lignes par jour,
- pendant l’
insert
, tu traites 3 batches de 100k lignes, - au 2e batch, une erreur se produit (ex : problème de type ou clé dupliquée).
❌ Résultat sans transaction :
100k lignes insérées → crash → modèle dans un état partiellement mis à jour, donc incohérent pour les downstreams.
✅ Résultat avec transaction + savepoint :
Rollback jusqu’au dernier point sûr → aucune donnée corrompue.
⚙️ dbt et les transactions
- dbt exécute les modèles dans une transaction par défaut (si le moteur SQL le supporte, comme Snowflake, PostgreSQL, etc.).
- tu peux gérer manuellement les transactions dans les modèles SQL avec Jinja.
🔧 Exemple de modèle incrémental avec savepoints
{% if is_incremental() %}
begin;
savepoint before_batch;
insert into {{ this }}
select *
from {{ ref('stg_events') }}
where event_date > (select max(event_date) from {{ this }});
-- Simuler une erreur volontaire (ex : test)
{% if var('simulate_error', false) %}
{{ exceptions.error("Erreur simulée") }}
{% endif %}
release savepoint before_batch;
commit;
{% else %}
-- Mode full-refresh ou initial
select *
from {{ ref('stg_events') }}
{% endif %}
🔁 En cas d’erreur
- si
simulate_error = true
, l’erreur est levée, - tout est rollbacké jusqu’à la sauvegarde ou début de transaction,
- aucune donnée partiellement insérée ne reste dans la table cible.
📌 Et si tu veux encore plus de granularité ?
Tu peux créer plusieurs savepoint
à l’intérieur de ton modèle :
savepoint part1;
-- traitement 1
release savepoint part1;
savepoint part2;
-- traitement 2
release savepoint part2;
✅ Avantages de cette méthode
Avantage | Détail |
---|---|
🔐 Cohérence garantie | Pas de demi-mise-à-jour en cas d’échec |
🛠️ Récupération plus fine | Possibilité de relancer uniquement ce qui a échoué |
🔁 Compatible avec modèles incrémentaux | dbt laisse le contrôle si tu le veux |
🔎 Debug plus facile | Tu sais où ça a échoué grâce au nom du savepoint |
⚠️ Limitations
- Les transactions avec savepoints ne sont pas supportées par BigQuery (pas de
BEGIN
,COMMIT
,ROLLBACK
). - Cela fonctionne parfaitement avec : PostgreSQL, Snowflake, Redshift, Databricks SQL.