這很重要
寫入 Unity Catalog 管理的 Iceberg 表格的交易則在 私人預覽中。 要加入此預覽,請提交 管理的 Iceberg 表格預覽報名表單。
交易允許你協調多個 SQL 語句和資料表間的操作。 所有變更必須同時成功或同時回復,確保資料在操作及資料表中一致性。 交易內容包括 ACID 特性:原子性、一致性、隔離性與耐久性。 請參見Azure Databricks?的ACID保證是什麼。
交易可搭配 儲存程序 與 SQL 腳本 來建立關鍵任務倉儲工作負載。
以下範例展示了一筆交易:
非互動式
BEGIN ATOMIC
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
INSERT INTO audit_log VALUES (1, 2, 100, current_timestamp());
END;
互動式
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
INSERT INTO audit_log VALUES (1, 2, 100, current_timestamp());
COMMIT;
這三句話一起承諾。 若任何敘述失敗,所有變更都會回滾,Databricks 也會終止該交易且不會有副作用。
欲實際操作交易,請參考 教學:跨桌協調交易。
要求
要執行涉及多個語句或多個資料表的交易:
- 所有要寫入的資料表必須:
- Be Unity Catalog 管理的資料表(Delta Lake 或 Iceberg)
- 啟用目錄提交
- 使用支援的運算:
交易模式
Azure Databricks 支援兩種交易模式:
| 模式 | 語法 | 承諾 | 回滾 | 最適合用於 |
|---|---|---|---|---|
| 非互動式 | 原子化合物陳述 | 成功時自動 | 錯誤時自動 | 固定序列、排定的工作任務 |
| 互動式 | 開始交易; 承諾; | 說明書 | 說明書 | 條件邏輯、驗證與除錯、JDBC、ODBC、PyODBC |
關於兩種模式的詳細語法、範例及使用模式,請參見 交易模式。
支援的作業
你可以在交易中使用以下操作:
| 運算 | 說明 |
|---|---|
SELECT (子選擇) |
查詢資料並驗證結果 |
VALUES 子句 |
產生測試資料或常數值 |
INSERT (包括所有變體) |
新增列 |
UPDATE |
修改現有的列 |
COPY INTO |
將檔案資料載入 Delta 表格 |
DELETE FROM |
移除資料列 |
MERGE INTO |
Upsert 模式結合了插入、更新與刪除 |
| USE CATALOG 與 USE SCHEMA | 設定交易中陳述句的當前目錄或架構 |
| EXECUTE IMMEDIATE | 執行一個你在執行時動態建構的 SQL 陳述句 |
| DESCRIBE TABLE | 回傳關於資料表的元資料,例如其欄位與屬性 |
| SHOW COLUMNS | 在表格中列出欄位 |
| GET 診斷語句 | 取得診斷資訊,例如活躍交易狀態或最近語句影響的列數 |
支援的讀取源與寫入匯
交易允許你從 Unity 目錄資料表(Delta Lake 和 Iceberg)、串流資料表、檢視資料以及實體化檢視中讀取資料。
由於具備 ACID 保證,如 Delta Lake 和 Iceberg 等開放資料表格式可在交易中作為讀取來源與寫入目標受到支援。 要從非交易來源讀取,請使用 allow_nontransactional_read 提示。 參見「 從非交易來源讀取 」及 「範例:非交易讀取」。
從非交易來源閱讀
警告
非交易式讀取無法重複。 交易過程中對來源資料的同時變更可能導致讀取不一致。
交易允許你從非交易來源讀取資料。 非交易來源包括使用 Parquet、Avro、CSV 和 JSON 檔案格式的外部資料表,以及 使用 JDBC 的聯邦資料表。 要閱讀非交易性來源,請以名稱引用來源並使用 allow_nontransactional_read 提示。
在交易中,你也可以查詢 information_schema。
你可以直接用 read_files table-valued 函式讀取檔案。
不支援基於路徑的存取。 如果你直接以路徑(例如 FROM parquet.`/path/to/data`)來參考檔案,交易就會 PATH_BASED_ACCESS 以錯誤方式失敗。
以下程式碼範例展示了如何在外部資料表中使用 JSON 的提示:
BEGIN TRANSACTION;
-- Non-transactional source, hint required
INSERT INTO transactional_table
SELECT col1, col2
FROM external_json_table
WITH (allow_nontransactional_read = true);
COMMIT;
範例:非交易讀取
以下範例展示了使用 Parquet 從外部資料表進行非交易式讀取。 這個例子需要你有一個既有的外部位置,並且有讀寫權限。
請參閱 連線至 Azure Data Lake Storage Gen2(ADLS Gen2)外部位置。
要將 Parquet 來源註冊為命名的外部資料表,請執行以下操作:
CREATE TABLE main.default.external_parquet_table
USING PARQUET
LOCATION 'abfss://my-container@my-storage-account.dfs.core.windows.net/path/to/data'; -- existing external location
若要在交易中同時讀取非交易型 Parquet 來源與使用 Delta Lake 管理的表格,執行以下操作:
BEGIN ATOMIC
-- Non-transactional source, hint required
INSERT INTO transactional_table
SELECT col1, col2
FROM external_parquet_table
WITH (allow_nontransactional_read = true);
-- Managed table source, no hint is required
INSERT INTO another_table
SELECT * FROM managed_delta_table;
END;
交易隔離
交易允許所有語句間重複讀取。 當你在交易中存取資料表時,Azure Databricks 會在首次存取時擷取該資料表的一致快照。 該資料表的所有後續讀取都會使用這個快照,因此即使其他使用者同時修改相同的資料表,讀取結果也會保持一致。
以下範例中,交易 products 中的第一個查詢會擷取一個一致的快照:
非互動式
BEGIN ATOMIC
SELECT * FROM products WHERE product_id = 1001;
SELECT * FROM products WHERE product_id = 1001;
END;
互動式
BEGIN TRANSACTION;
SELECT * FROM products WHERE product_id = 1001;
SELECT * FROM products WHERE product_id = 1001;
COMMIT;
接著,假設在第二個查詢開始前,有另一位使用者同時更新了該列:product_id = 1001
UPDATE products SET price = 29.99 WHERE product_id = 1001;
由於快照是在第一次存取時擷取的,第二次查詢 products 會回傳原始的列,而非更新後的那一列。
衝突偵測與並行處理
Azure Databricks 使用 optimistic concurrency control. 交易可不鎖定,衝突會在提交時偵測到。 當你提交時,Azure Databricks 會檢查其他交易是否在你的交易開始後修改了相同的資料。 如果存在衝突,你的交易就會失敗。 對於非互動式交易,回滾也會自動進行。 對於互動式交易,你必須明確執行 ROLLBACK 以清除交易狀態,才能開始新的交易。
非互動式交易支援列級並行。 當目標資料表啟用列 層級並行 時,兩個交易可以修改同一資料檔中不同的列而不會衝突。
互動式交易支援資料表層級的並行性。
衝突情境
| 情境 | 說明 |
|---|---|
| 寫入衝突 | 兩個交易會更新或刪除相同的資料列。 |
| 寫入-讀取衝突 | 另一筆交易修改了你筆交易讀取的列。 僅適用於可序列化的隔離。 |
| 幻讀問題 | 另一筆交易新增了與你交易讀取的謂詞相符的新列。 適用於可寫序列化(WriteSerializable)與可序列化隔離(Serializable)。 |
| 元資料衝突 | 另一筆交易改變了資料表結構或屬性。 |
關於交易的隔離層級與衝突解決,請參見 交易模式。 關於Azure Databricks上Delta Lake表格的隔離層級及寫入衝突行為的資訊,請參閱Azure Databricks上的最佳化建議。
交易在 Delta 日誌中的呈現方式
每筆成功的交易都會以單一條目出現在資料表的 Delta 日誌中,無論在交易中執行了多少個個別語句。 這能提供乾淨的稽核軌跡並簡化回滾作業。
交易中的個別操作可作為 JSON 形式的中繼資料在 Delta 日誌中取得。
錯誤處理與回滾
下表說明了兩種交易類型的錯誤回滾如何發生:
| 情境 | 非互動交易的行為 | 互動式交易的行為 |
|---|---|---|
| 陳述句失敗 | 任何引發錯誤的語句都會立即自動回滾。 | 如果會話仍在進行中,必須明確執行 ROLLBACK 來丟棄變更。 |
| 驗證邏輯或商業規則失敗 | 用 SIGNAL 來拋出例外並觸發自動回滾。 |
執行 ROLLBACK 來丟棄變更。 |
| 會話斷線 | 交易會自動回滯。 | 交易會自動回滯。 |
| 暫停 | 總時長達 48 小時後自動回滾。 | 10分鐘未使用或累計持續時間達到48小時後將自動回復(詳見限制)。 交易會無副作用地終止,但如果會話仍在進行中,你必須明確執行 ROLLBACK 來清除交易狀態。 |
對於交互交易,你可以明確使用 ROLLBACK 陳述式來回復。 這可讓您根據驗證邏輯或業務規則,或在陳述式執行失敗但工作階段仍維持作用中時,捨棄變更。
最佳做法
遵循這些做法以減少衝突並優化交易效能。
避免衝突
- 保持交易時間短:長期交易增加衝突可能性並延長資源保存時間。
- 及早驗證:在交易開始前檢查前提條件,以快速終止可能失敗的操作。
-
使用
BEGIN ATOMIC進行資料列層級的並行處理:非互動式交易(BEGIN ATOMIC ... END;)會在資料列層級偵測衝突,與互動式交易使用的資料表層級偵測相比,可減少衝突。 參見 非互動交易。 - 建置重試邏輯:交易隨時可能因衝突而失敗。 在應用程式中建立重試邏輯,並用全新資料重試失敗的交易。
- 每個互動式工作階段開始時先執行回滾:在互動式工作階段開始時執行 ROLLBACK,以清除任何先前存在的交易狀態。
使用來自不同客戶的交易
交易在各種客戶端介面間運作:
-
SQL 編輯器與筆記本:直接在 SQL 儲存格中使用
BEGIN ATOMIC ... END;或BEGIN TRANSACTION; ... COMMIT;語法,或在 Python/Scala 筆記本中使用spark.sql()。 請參見 交易模式。 -
JDBC 應用程式:使用 JDBC API 方法(
setAutoCommit(false),commit(),rollback()),搭配 Databricks JDBC 驅動程式 版本 3.0.5 及以上。 參見 使用交易的範例。 關於交易中不支援的 JDBC 操作清單,請參見 不支援的 JDBC 操作。 - ODBC 應用程式:使用 Databricks ODBC 驅動 程式版本 2.10.0 及以上。 關於交易中未支援的 ODBC 操作清單,請參見 不支援的 ODBC 操作。
-
Python 應用程式:將 Databricks SQL 連接器與
autocommit=False一起使用。 請參見 Databricks SQL 連接器以了解 Python。 關於交易中不支援的Python連接器操作列表,請參見 Unsupported Python連接器操作。 - 語句執行 API:透過 API 呼叫使用 SQL 語法執行交易。 請參見「 使用語句執行 API」。
局限性
以下限制適用於交易:
| 限度 | 說明 |
|---|---|
| 互動式交易衝突 | 互動式交易(BEGIN TRANSACTION;... COMMIT;)使用比非互動式交易更保守的衝突偵測,且可以在資料表層級發生衝突,除非是 INSERT 不從目標資料表讀取的操作。 當列層級衝突偵測很重要時,請使用非互動式交易(ATOMIC 複合語句)。 參見 非互動交易。 |
| 寫入目標 | 你只能寫入啟用了catalogManaged表格功能的由Unity Catalog管理的Delta或Iceberg表。 請參閱 提交紀錄。 |
| 不支援 DDL 作業 | 在交易之外執行 DDL 操作,例如 CREATE TABLE、 ALTER TABLE或 DROP TABLE。 關於交易所支援的操作,請參見 支援的操作。 |
| 部分不支援的元資料操作 | 某些中繼資料操作無論使用何種協定,在交易中都無法運作。 這包括基於 Thrift RPC 的元資料呼叫(如 JDBC DatabaseMetaData 方法與 ODBC 目錄函式)、基於 SQL 的枚舉指令(如 SHOW TABLES 和 SHOW DATABASES),以及 SELECT 對系統資料表的查詢。 在交易之外執行這些元資料操作。 |
COPY INTO 並行性 |
執行指令 COPY INTO 的交易若同時執行另一個 COPY INTO 指令寫入同一資料表並先提交,則該交易失敗。 |
適用於 MERGE 的資料列層級並行 |
AWS GovCloud 或單用戶(專用)叢集不支援列級並行 MERGE 操作。 在這些平台上, MERGE 操作使用表層級的並行。 參見 列層級並行。 |
| 表格與視圖限制 | 一個交易可從最多 100 個資料表讀取或寫入,最多可讀取 100 個視圖。 每個資料表格在交易中最多可有 100 個中間提交記錄。 |
| 不支援時間旅行 | 你不能在交易中使用 時間旅行功能 。 |
| 閒置暫停 | 互動式交易在逾 10 分鐘不活躍後會回復。 交易會無副作用地終止,但如果會話仍在進行中,你必須明確執行 ROLLBACK 來清除交易狀態。 |
| 世系 | 交易在每次讀寫時會產生數據來源。 即使交易被回滾,血緣事件仍然存在。 |
| 最長持續時間 | 所有交易會在從開始計算的總時長達到48小時後自動回滾。 對於互動式交易,交易會無副作用地終止,但如果會話仍在進行中,必須明確執行 ROLLBACK 來清除交易狀態。 |
| OpenSharing 共享資料表需求 | OpenSharing 提供者必須共享一個表格,讓接收者能在該 表格 WITH HISTORY 上執行交易。 接收者可以使用任何類型的運算方式執行交易。 |
| OpenSharing 接收者的計算限制 | Azure Databricks 的接收者只能在共享檢視、實體化檢視、串流資料表以及非 Iceberg 的外部資料表上執行交易。 與其提供者同屬 Azure Databricks 帳號的接收者必須使用共享或無伺服器運算。 不同帳號的接收者必須使用無伺服器運算。 |
| OpenSharing 原始碼表衝突 | OpenSharing 接收者不能在單一交易中引用同一來源資料表的共享視圖與共享資料表。 |