Aller au contenu principal

Modes de transaction

info

Aperçu

Les transactions qui écrivent dans les tables Iceberg gérées par Unity Catalog sont en préversion privée. Pour rejoindre cette préversion, soumettez le formulaire d'inscription à la préversion des tables Iceberg gérées.

Les transactions sur Databricks prennent en charge deux modes :

  • Non interactif (BEGIN ATOMIC) : effectue des commits ou des restaurations automatiques. Idéal pour les Jobs planifiés et les séquences d'instructions fixes.
  • **Interactif** BEGIN TRANSACTION() : Vous donne un contrôle manuel sur les opérations de commit et d'annulation. Idéal pour la validation, le debugging et les clients JDBC.

Pour connaître les exigences et obtenir un aperçu des transactions, consultez Transactions. Pour une mise en pratique des deux modes, consultez Didacticiel : Coordonner les transactions entre les tables.

remarque

Toutes les tables écrites dans une transaction multi-déclaration, multi-table doivent :

Transactions non interactives

Les transactions non interactives utilisent le scripting SQL avec le mot-clé ATOMIC. Le bloc d'instruction composée ATOMIC exécute toutes les instructions comme une seule unité atomique. Tous réussissent ou tous échouent ensemble.

Compute pris en charge : Tout SQL Warehouse, compute Serverless ou cluster exécutant Databricks Runtime 18.0 et versions ultérieures.

Syntaxe prise en charge : Prend en charge les blocs SQL, Scala spark.sql et PySpark spark.sql.

remarque

Vous pouvez utiliser des transactions non interactives dans le forEachBatch de Structured Streaming en appelant spark.sql("BEGIN ATOMIC ... END;"). Toutefois, les points de contrôle Structured Streaming n'avancent pas de manière transactionnelle.

Syntaxe

SQL
BEGIN ATOMIC
statement1;
statement2;
statement3;
END;

Databricks commit automatiquement toutes les modifications si toutes les instructions réussissent. Si une instruction échoue, Databricks annule automatiquement toutes les modifications.

Utiliser dans l’éditeur SQL

Exécutez les transactions non interactives directement dans l'éditeur SQL. Sélectionnez l'intégralité du bloc d'instructions composées ATOMIC et exécutez-le en tant qu'instruction unique :

SQL
BEGIN ATOMIC
DELETE FROM staging_sales WHERE load_date < current_date() - INTERVAL 7 DAYS;

INSERT INTO staging_sales
SELECT * FROM raw_sales WHERE load_date = current_date();

MERGE INTO sales AS target
USING staging_sales AS source
ON target.sale_id = source.sale_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
END;

Utiliser dans les Notebooks

Exécutez des transactions non interactives dans des Notebooks à l'aide de cellules SQL ou d'APIs programmatiques.

SQL
BEGIN ATOMIC
UPDATE inventory SET quantity = quantity - 10 WHERE product_id = 2001;
UPDATE inventory SET quantity = quantity + 10 WHERE product_id = 2002;
INSERT INTO inventory_moves (from_product, to_product, quantity, move_date)
VALUES (2001, 2002, 10, current_date());
END;

Utiliser dans les Jobs planifiés

Les transactions non interactives fonctionnent bien dans les jobs planifiés, car elles gèrent automatiquement le commit et le rollback :

SQL
BEGIN ATOMIC
-- Clear previous staging data
DELETE FROM staging_daily_sales WHERE load_date = current_date();

-- Load new data
INSERT INTO staging_daily_sales
SELECT sale_id, customer_id, amount, sale_date, current_date() as load_date
FROM raw_sales
WHERE sale_date = current_date() - INTERVAL 1 DAY;

-- Validate row count (fails transaction if no data)
IF (SELECT COUNT(*) FROM staging_daily_sales WHERE load_date = current_date()) = 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'No sales data loaded for yesterday';
END IF;

-- Merge into production
MERGE INTO daily_sales AS target
USING staging_daily_sales AS source
ON target.sale_id = source.sale_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
END;

Si une instruction échoue, y compris l'assertion, l'intégralité de la transaction est annulée automatiquement.

Utiliser avec JDBC

Les clients externes peuvent exécuter des transactions non interactives.

Java
String sql = """
BEGIN ATOMIC
INSERT INTO orders (order_id, total) VALUES (1001, 500.00);
UPDATE customers SET last_order = CURRENT_DATE() WHERE customer_id = 5001;
END;
""";

Statement stmt = conn.createStatement();
stmt.execute(sql);

Utiliser avec l'API Statement Execution

Exécutez des transactions non interactives à l’aide de l’ API Statement Execution:

Python
import requests

sql = """
BEGIN ATOMIC
INSERT INTO sales (sale_id, amount) VALUES (3001, 750.00);
UPDATE daily_totals SET total = total + 750.00 WHERE sale_date = CURRENT_DATE();
END;
"""

response = requests.post(
f"{workspace_url}/api/2.0/sql/statements",
headers={&quot;Authorization&quot;: f&quot;Bearer {token}&quot;},
json={
&quot;warehouse_id&quot;: warehouse_id,
&quot;statement&quot;: sql,
&quot;wait_timeout&quot;: &quot;30s&quot;
}
)

Modèles ETL

Les modèles suivants illustrent les workflows ETL courants utilisant des transactions non interactives.

Modèle de préparation et de validation

Ce modèle charge des données dans une zone de transit, valide la qualité des données et Merge les enregistrements validés dans des tables de production :

SQL
BEGIN ATOMIC
-- Load into staging
INSERT INTO staging_customers
SELECT * FROM external_source
WHERE ingest_date = current_date();

-- Validate data quality
IF (SELECT COUNT(*) FROM staging_customers WHERE email NOT LIKE '%@%') > 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid email addresses found';
END IF;

-- Merge validated data
MERGE INTO customers AS target
USING staging_customers AS source
ON target.customer_id = source.customer_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;

-- Update metadata
UPDATE etl_metadata
SET last_load_date = current_date(),
rows_processed = (SELECT COUNT(*) FROM staging_customers)
WHERE table_name = 'customers';
END;

Modèle de tables de dimension et de faits

Ce modèle met à jour les tables de dimension avant de charger les tables de faits pour maintenir l'intégrité référentielle :

SQL
BEGIN ATOMIC
-- Update dimension tables first
MERGE INTO dim_products AS target
USING staging_products AS source
ON target.product_id = source.product_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;

MERGE INTO dim_customers AS target
USING staging_customers AS source
ON target.customer_id = source.customer_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;

-- Then load fact table with foreign key references
INSERT INTO fact_sales
SELECT s.sale_id, p.product_key, c.customer_key, s.sale_amount, s.sale_date
FROM staging_sales s
JOIN dim_products p ON s.product_id = p.product_id
JOIN dim_customers c ON s.customer_id = c.customer_id;
END;

Gestion des erreurs

Lorsqu'une instruction échoue dans un bloc BEGIN ATOMIC ... END;, Databricks annule toutes les modifications et renvoie un message d'erreur.

Conseils de debugging :

  1. Examinez le message d'erreur pour identifier quelle instruction a échoué.
  2. Testez les déclarations individuellement en dehors du bloc de transaction.
  3. Ajoutez des contrôles de validation à l’aide de SIGNAL pour échouer avec des messages d’erreur personnalisés
  4. Interrogez l'historique des transactions pour un contexte supplémentaire.

Transactions interactives

Les transactions interactives vous donnent un contrôle explicite sur les limites des transactions. Vous lancez manuellement une transaction, exécutez des instructions et commit ou annulez explicitement.

Compute pris en charge : SQL Warehouse uniquement.

Syntaxe prise en charge : SQL uniquement.

Syntaxe

Pour commit :

SQL
BEGIN TRANSACTION;
statement1;
statement2;
COMMIT;

Pour annuler :

SQL
BEGIN TRANSACTION;
statement1;
statement2;
ROLLBACK;

Validez avant de commit

Utilisez des transactions interactives pour valider les résultats avant de commit :

SQL
BEGIN TRANSACTION;

-- Load staging data
INSERT INTO staging_customers
SELECT * FROM external_customers
WHERE load_date = current_date();

-- Validate and commit or rollback
BEGIN
DECLARE duplicate_count INT;
SET duplicate_count = (
SELECT COUNT(*) FROM (
SELECT customer_id, COUNT(*) as cnt
FROM staging_customers
WHERE load_date = current_date()
GROUP BY customer_id
HAVING COUNT(*) > 1
)
);

IF duplicate_count > 0 THEN
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Duplicate customers found in staging data';
ELSE
MERGE INTO customers AS target
USING staging_customers AS source
ON target.customer_id = source.customer_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
COMMIT;
END IF;
END;

Restauration explicite

Annulez une transaction lorsque la validation échoue ou que la logique métier nécessite de rejeter les modifications :

SQL
BEGIN TRANSACTION;

UPDATE inventory
SET quantity = quantity - 50
WHERE product_id = 2001;

-- Check if quantity would go negative
BEGIN
DECLARE new_quantity INT;
SET new_quantity = (SELECT quantity FROM inventory WHERE product_id = 2001);

IF new_quantity < 0 THEN
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Insufficient inventory for product 2001';
ELSE
COMMIT;
END IF;
END;

Utiliser avec JDBC

Le Driver JDBC prend en charge l'exécution d'instructions DML à l'aide de executeUpdate() au sein de transactions. Pour une liste d'instructions DML prises en charge, consultez Opérations prises en charge.

Les clients JDBC utilisent des transactions interactives en désactivant le mode auto-commit :

Java
Connection conn = DriverManager.getConnection(jdbcUrl, properties);

try {
conn.setAutoCommit(false); // Start transaction mode
Statement stmt = conn.createStatement();

stmt.executeUpdate("INSERT INTO accounts (account_id, balance) VALUES (1001, 5000)");
stmt.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE account_id = 1001");

conn.commit(); // Commit the transaction

} catch (SQLException e) {
conn.rollback(); // Roll back on error
throw e;
} finally {
conn.close();
}

Opérations JDBC non prises en charge

Les opérations JDBC suivantes ne sont pas prises en charge dans les transactions interactives :

Catégorie

Non pris en charge

Basculement de catalogue ou de schéma

Connection.setCatalog() et Connection.setSchema()

Modifications de la configuration de session

Connection.setClientInfo() pour les propriétés au niveau de la session telles que TIMEZONE et ANSI_MODE

Toutes les DatabaseMetaData (tous les protocoles)

Toutes les méthodes DatabaseMetaData.*

Métadonnées de PreparedStatement.

PreparedStatement.getMetaData()

Procédures stockées

CALL procedure_name()

Catégorie

Non pris en charge

Basculement de catalogue ou de schéma

Connection.setCatalog() et Connection.setSchema()

Modifications de la configuration de session

Connection.setClientInfo() pour les propriétés au niveau de la session telles que TIMEZONE et ANSI_MODE

Toutes les DatabaseMetaData (tous les protocoles)

Toutes les méthodes DatabaseMetaData.*

Métadonnées de PreparedStatement.

PreparedStatement.getMetaData()

Procédures stockées

CALL procedure_name()

Utiliser avec ODBC

Le driver ODBC prend en charge l’exécution des instructions DML à l’aide de SQLExecute() et SQLExecDirect() dans les transactions. Pour obtenir la liste des instructions DML prises en charge, consultez Opérations prises en charge.

Les clients ODBC peuvent utiliser des transactions interactives avec le Driver ODBC Databricks à l'aide des fonctions standard de gestion des transactions ODBC.

remarque

Vous devez désactiver AutoCommit pour utiliser les transactions. Pour désactiver AutoCommit lors de l'exécution, définissez UseNativeQuery sur 1. Voir la prise en charge des requêtes ANSI SQL-92 dans ODBC.

Opérations ODBC non prises en charge

Les opérations ODBC suivantes ne sont pas prises en charge dans les transactions interactives :

Catégorie

Non pris en charge

Toutes les fonctions du catalogue

SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns, SQLPrimaryKeys, SQLForeignKeys, SQLTablePrivileges, SQLColumnPrivileges, SQLProcedures, SQLProcedureColumns

Définition des attributs de connexion

Changement de catalogue, modifications du niveau d'isolation et modifications du mode d'accès à l'aide de SQLSetConnectAttr()

Traduction SQL

SQLNativeSql

Catégorie

Non pris en charge

Toutes les fonctions du catalogue

SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns, SQLPrimaryKeys, SQLForeignKeys, SQLTablePrivileges, SQLColumnPrivileges, SQLProcedures, SQLProcedureColumns

Définition des attributs de connexion

Changement de catalogue, modifications du niveau d'isolation et modifications du mode d'accès à l'aide de SQLSetConnectAttr()

Traduction SQL

SQLNativeSql

Utiliser avec le connecteur Databricks SQL pour Python

Le connecteur Databricks SQL pour Python prend en charge l’exécution d’instructions DML à l’aide de cursor.execute() au sein des transactions. Pour une liste d'instructions DML prises en charge, consultez Opérations prises en charge.

Les applications Python peuvent utiliser des transactions interactives avec le connecteur Databricks SQL pour Python en définissant autocommit=False:

Python
from databricks import sql

with sql.connect(
server_hostname="dbc-a1b2345c-d6e7.cloud.databricks.com",
http_path="sql/1.0/warehouses/abc123def456",
access_token="your-access-token",
autocommit=False
) as connection:
with connection.cursor() as cursor:
cursor.execute("INSERT INTO accounts (account_id, balance) VALUES (1001, 5000)")
cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE account_id = 1001")
connection.commit()

Opérations du connecteur Python non prises en charge

Les opérations suivantes du connecteur Python ne sont pas prises en charge dans les transactions interactives :

Catégorie

Non pris en charge

Toutes les métadonnées

cursor.catalogs(), cursor.schemas(), cursor.tables(), cursor.columns()

Catégorie

Non pris en charge

Toutes les métadonnées

cursor.catalogs(), cursor.schemas(), cursor.tables(), cursor.columns()

Limitations du Driver pour les transactions interactives

Les limitations suivantes s'appliquent à tous les drivers lors de l'utilisation de transactions interactives.

Les opérations de Metadata ne sont pas prises en charge dans les transactions interactives. Les Opérations suivantes peuvent échouer au sein d'une transaction indépendamment du Driver ou du protocole :

Driver/Protocole

Type

Méthodes

JDBC

DatabaseMetaData

getCatalogs(), getSchemas(), getTables(), getColumns(), getTypeInfo()

ODBC

Fonctions du catalogue

SQLTables, SQLColumns, SQLGetTypeInfo

Connecteur Python

Méthodes de métadonnées

cursor.catalogs(), cursor.schemas(), cursor.tables(), cursor.columns()

SQL

Commandes de métadonnées

SHOW TABLES et SHOW DATABASES

Driver/Protocole

Type

Méthodes

JDBC

DatabaseMetaData

getCatalogs(), getSchemas(), getTables(), getColumns(), getTypeInfo()

ODBC

Fonctions du catalogue

SQLTables, SQLColumns, SQLGetTypeInfo

Connecteur Python

Méthodes de métadonnées

cursor.catalogs(), cursor.schemas(), cursor.tables(), cursor.columns()

SQL

Commandes de métadonnées

SHOW TABLES et SHOW DATABASES

Databricks vous recommande d'exécuter ces opérations de métadonnées en dehors des transactions.

attention

L’exécution de transactions sur plusieurs threads sur un seul objet de connexion Driver entraîne un comportement indéfini. Exécutez une seule transaction à la fois sur chaque objet de connexion.

Comportement d'isolation

Les modifications non validées dans une transaction interactive ne sont visibles que par votre session. Les modifications ne sont visibles par les autres sessions qu'une fois que vous exécutez COMMIT;.

remarque

Les transactions interactives utilisent une détection des conflits plus conservatrice que les transactions non interactives et peuvent entrer en conflit au niveau de la table (sauf pour les ajouts inconditionnels). Pour la détection des conflits au niveau des lignes, utilisez des transactions non interactives (BEGIN ATOMIC ... END;).

  1. Pour vérifier l'isolation, créez la table d'échantillons si elle n'existe pas :
SQL
CREATE TABLE IF NOT EXISTS sample_accounts (
id INT,
account_name STRING,
balance DECIMAL(10,2)
) USING DELTA
TBLPROPERTIES ('delta.feature.catalogManaged' = 'supported');
  1. Dans la même session, start une transaction et apportez une modification :

    SQL
    BEGIN TRANSACTION;
    INSERT INTO sample_accounts VALUES (10, 'Test', 100.00);
  2. Dans un onglet d'éditeur SQL ou une session de Notebook séparé (pas une nouvelle cellule dans le même Notebook), interrogez la table :

    SQL
    -- Run this in the SECOND session
    SELECT * FROM sample_accounts WHERE id = 10;

    Ceci renvoie 0 ligne, car la modification non validée n'est pas visible en dehors de votre première session.

  3. Retournez à votre première session et commit :

    SQL
    COMMIT;
  4. Query de la deuxième session à nouveau :

    SQL
    -- Run this in the SECOND session
    SELECT * FROM sample_accounts WHERE id = 10;

    La ligne est visible car la transaction a été validée.

Cette isolation empêche les autres utilisateurs de lire des données qui pourraient être annulées.

Choisissez un mode de transaction

Scénario

Mode recommandé

Jobs ETL planifiés

Non-interactif : le commit ou le rollback automatique simplifie la gestion des erreurs.

Séquences d'instructions fixes

Non-interactif : syntaxe plus simple, aucun commit manuel nécessaire.

Validation des données avant commit

Interactif : inspectez les résultats et décidez s’il faut les commit

Applications JDBC nécessitant un contrôle manuel

Interactif : modèles de transactions de base de données standard.

Scénario

Mode recommandé

Jobs ETL planifiés

Non-interactif : le commit ou le rollback automatique simplifie la gestion des erreurs.

Séquences d'instructions fixes

Non-interactif : syntaxe plus simple, aucun commit manuel nécessaire.

Validation des données avant commit

Interactif : inspectez les résultats et décidez s’il faut les commit

Applications JDBC nécessitant un contrôle manuel

Interactif : modèles de transactions de base de données standard.

Ressources supplémentaires