Tutorial: Coordenar transações entre tabelas
Visualização
Transações que gravam no Unity Catalog gerenciam tabelas Delta e estão em Pré-visualização Pública.
Transações que gravam em tabelas Iceberg gerenciadas Unity Catalog estão em Pré-visualização Privada. Para join desta pré-visualização, envie o formulário de inscrição para a pré-visualização das mesas Iceberg.
Neste tutorial, são utilizados ambos os modos de transação para coordenar atualizações em várias declarações e tabelas no Databricks: não interativo (BEGIN ATOMIC), que realiza commit automaticamente, e interativo (BEGIN TRANSACTION), que oferece controle explícito. O tutorial também demonstra como usar transações com procedimentos armazenados e SQL Scripting.
Requisitos
-
Ambiente : Acesso a um workspace Databricks .
-
Computação : Os tipos compute suportados variam de acordo com o modo de transação:
- Um SQL warehouse clássico ou serverless suporta ambos os modos de transação.
- computesem servidor suporta apenas transações não interativas.
- clusters clássicos que executam Databricks Runtime 18.0 ou superior suportam apenas transações não interativas.
-
Privilégios :
CREATE TABLEem um esquema Unity Catalog .
Configure tabelas de exemplo
Todas as tabelas que são gravadas em uma transação com várias instruções e várias tabelas devem:
- Unity Catalog gerenciar tabelas (Delta ou Iceberg)
- Ativar a confirmação do catálogo
Crie duas tabelas de exemplo no EditorSQL ou em um Notebook:
-- Account data
CREATE TABLE IF NOT EXISTS sample_accounts (
id INT,
account_name STRING,
balance DECIMAL(10,2)
) USING DELTA
TBLPROPERTIES (
'delta.feature.catalogManaged' = 'supported'
);
-- Transaction records
CREATE TABLE IF NOT EXISTS sample_transactions (
id INT,
account_id INT,
transaction_type STRING,
amount DECIMAL(10,2)
) USING DELTA
TBLPROPERTIES (
'delta.feature.catalogManaged' = 'supported'
);
Para habilitar transações em uma tabela existente, realize a execução de:
ALTER TABLE <table_name> SET TBLPROPERTIES ('delta.feature.catalogManaged' = 'supported');
Insira dados de amostra em ambas as tabelas:
INSERT INTO sample_accounts VALUES
(1, 'Alice', 1000.00),
(2, 'Bob', 500.00);
INSERT INTO sample_transactions VALUES
(1, 1, 'deposit', 100.00);
Verifique a configuração:
SELECT * FROM sample_accounts;
SELECT * FROM sample_transactions;
Saída:
sample_accounts:
id account_name balance
1 Alice 1000.00
2 Bob 500.00
sample_transactions:
id account_id transaction_type amount
1 1 deposit 100.00
Transações não interativas
Transações não interativas usam a sintaxe BEGIN ATOMIC ... END; . A execução de todas as instruções ocorre como uma única unidade atômica. Se todas as instruções forem bem-sucedidas, o Databricks realiza o commit automaticamente. Se alguma instrução falhar, o Databricks reverte todas as alterações automaticamente. Para obter detalhes sobre a sintaxe e os padrões de uso, consulte transações não interativas.
execução de uma transação bem-sucedida
Atualize ambas as tabelas atomicamente:
BEGIN ATOMIC
-- Update Alice's account balance
UPDATE sample_accounts
SET balance = balance + 100.00
WHERE id = 1;
-- Record the deposit transaction
INSERT INTO sample_transactions
VALUES (2, 1, 'deposit', 100.00);
END;
Verifique se o saldo de Alice agora é 1.100,00:
SELECT * FROM sample_accounts WHERE id = 1;
Verifique se dois registros de transação agora existem:
SELECT * FROM sample_transactions;
A atualização do saldo e o registro da transação foram criados simultaneamente. Se alguma das instruções tivesse falhado, nenhuma das alterações teria sido confirmada e o Databricks teria encerrado a transação sem efeitos colaterais.
Use SIGNAL para interromper uma transação sob uma condição.
Você pode usar SIGNAL dentro de um bloco BEGIN ATOMIC ... END; para falhar a transação quando uma condição definida pelo usuário não for atendida. Este exemplo insere um account com saldo negativo e, em seguida, usa SIGNAL para falhar a transação se a verificação do saldo falhar:
BEGIN ATOMIC
INSERT INTO sample_accounts VALUES (3, 'Charlie', -50.00);
IF (SELECT balance FROM sample_accounts WHERE id = 3) < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Account balance cannot be negative';
END IF;
END;
O SIGNAL levanta um erro, o que faz com que a transação inteira seja revertida automaticamente. Isso retorna zero linhas porque a inserção foi revertida:
SELECT * FROM sample_accounts WHERE id = 3;
Consulte a seção sobre reversão automática em caso de falha.
Realize uma execução de transação em que a primeira declaração é válida, mas a segunda faz referência a uma tabela que não existe:
BEGIN ATOMIC
-- Valid
INSERT INTO sample_accounts VALUES (4, 'David', 300.00);
-- Invalid
INSERT INTO non_existent_table VALUES (1, 2, 3);
END;
A transação falha com um erro. Isso retorna 0 linhas porque a transação inteira foi revertida:
SELECT * FROM sample_accounts WHERE id = 4;
Embora a primeira instrução INSERT fosse válida, ela foi revertida porque a segunda instrução falhou. Isso demonstra a garantia de "tudo ou nada" das transações.
Transações interativas
Transações interativas oferecem controle explícito sobre quando commit ou reverter a transação. Use BEGIN TRANSACTION para iniciar e, em seguida, confirme para salvar as alterações ou ROLLBACK para descartá-las.
confirmar alterações
Iniciar uma transação:
BEGIN TRANSACTION;
Fazer alterações (ainda não confirmadas):
INSERT INTO sample_accounts VALUES (5, 'Eve', 850.00);
UPDATE sample_accounts SET balance = balance + 50.00 WHERE id = 2;
Comprometa-se a tornar as mudanças permanentes:
COMMIT;
Verifique se a account da Eve agora está visível:
SELECT * FROM sample_accounts WHERE id = 5;
Verifique se o saldo de Bob agora é 550.00:
SELECT * FROM sample_accounts WHERE id = 2;
Reverter alterações
Iniciar uma nova transação:
BEGIN TRANSACTION;
Faça uma mudança:
INSERT INTO sample_accounts VALUES (6, 'Frank', 600.00);
Verifique se a alteração está visível em sua sessão (a linha não fica visível para outras sessões até ser confirmada):
SELECT * FROM sample_accounts WHERE id = 6;
Reverter para descartar a alteração:
ROLLBACK;
Isso retorna zero linhas porque a inserção foi revertida:
SELECT * FROM sample_accounts WHERE id = 6;
Utilizar com procedimentos armazenados e scripts SQL.
Você pode combinar transações com procedimentos armazenados para criar uma lógica de transação reutilizável. Este padrão é útil para operações complexas que você executa com frequência.
-
Crie as tabelas com a confirmação de catálogo ativada.
SQLCREATE SCHEMA IF NOT EXISTS main.retail;
CREATE TABLE IF NOT EXISTS main.retail.orders (
order_id STRING,
customer_id STRING,
amount DECIMAL(18,2)
) TBLPROPERTIES ('delta.feature.catalogManaged' = 'supported');
CREATE TABLE IF NOT EXISTS main.retail.orders_staging (
order_id STRING,
customer_id STRING,
amount DECIMAL(18,2),
batch_id STRING
) TBLPROPERTIES ('delta.feature.catalogManaged' = 'supported');
CREATE TABLE IF NOT EXISTS main.retail.total_sales (
customer_id STRING,
total_amount DECIMAL(18,2)
) TBLPROPERTIES ('delta.feature.catalogManaged' = 'supported'); -
Defina o procedimento armazenado
SQLCREATE OR REPLACE PROCEDURE main.retail.apply_order(
IN p_order_id STRING,
IN p_customer_id STRING,
IN p_order_amount DECIMAL(18,2)
)
LANGUAGE SQL
SQL SECURITY INVOKER
MODIFIES SQL DATA
AS
BEGIN
-- Insert the order
INSERT INTO main.retail.orders (order_id, customer_id, amount)
VALUES (p_order_id, p_customer_id, p_order_amount);
-- Update total sales per customer
MERGE INTO main.retail.total_sales AS t
USING (
SELECT
p_customer_id AS customer_id,
p_order_amount AS order_amount
) s
ON t.customer_id = s.customer_id
WHEN MATCHED THEN
UPDATE SET t.total_amount = t.total_amount + s.order_amount
WHEN NOT MATCHED THEN
INSERT (customer_id, total_amount)
VALUES (s.customer_id, s.order_amount);
END; -
Defina a transação
SQLBEGIN ATOMIC
-- Staging batch id for this transaction
DECLARE new_order_id STRING DEFAULT uuid();
DECLARE v_batch_id STRING DEFAULT uuid();
-- 1) Stage incoming customer and order rows
INSERT INTO main.retail.orders_staging (order_id, customer_id, amount, batch_id)
VALUES (new_order_id, 'CUST_123', 249.99, v_batch_id);
-- 2) Drive final writes from staging to production via stored procedure
FOR o AS
SELECT
order_id,
customer_id,
amount
FROM main.retail.orders_staging
WHERE batch_id = v_batch_id
DO
CALL main.retail.apply_order(
o.order_id,
o.customer_id,
o.amount
);
END FOR;
-- 3) Clean up processed staging rows
DELETE FROM main.retail.orders_staging
WHERE batch_id = v_batch_id;
END; -- 4) Commit the transaction
Se alguma parte da transação falhar, o Databricks reverte todas as alterações automaticamente.
Limpar
Remova as tabelas de exemplo:
DROP TABLE IF EXISTS sample_accounts;
DROP TABLE IF EXISTS sample_transactions;
DROP TABLE IF EXISTS main.retail.orders;
DROP TABLE IF EXISTS main.retail.orders_staging;
DROP TABLE IF EXISTS main.retail.total_sales;
Recursos adicionais
- Transações: Visão geral do suporte a transações.
- Modos de transação: Sintaxe e padrões detalhados para ambos os modos.
- Confirmação do catálogo: Habilite o suporte a transações em suas tabelas.
- Utilize transações de diferentes clientes: execute transações de aplicações JDBC, ODBC e Python .
- Declaração composta ATOMIC (transações não interativas)
- INICIAR TRANSAÇÃO (transações interativas)
- Commit
- REVERTER