簡介
本文將介紹 DB2 9.7 中引入的自治事務特性。自治事務與數據庫管理員和應用程序開發人員都有密切的關系。
本文將討論 DB2 9.7 for Linux, UNIX, and Windows。掌握 DB2 命令行處理器(CLP)和 SQL PL 的知識將非常有幫助。
要運行本文中的示例,需要訪問 DB2 9.7 for Linux, UNIX, and Windows 數據庫。
了解一些事務背景
事務是以文本、列(或同時使用兩者)的形式表現的來自真實世界的實體,將由數據庫管理系統處理。它們可以作為針對數據庫執行的操作,並且必須作為一組操作執行。
例如,從用戶 A 的帳戶將 X 金額傳輸到用戶 B 的帳戶,這個請求是一個非常簡單的事務。這個事務可以被分解為兩個 SQL 語句,如清單 1 所示:
清單 1. 簡單事務的示例Update table AccountInfo set CurrentBalance = CurrentBalance - X, where UserName=A
Update table AccountInfo set CurrentBalance = CurrentBalance + X, where UserName=B
只有在兩條 SQL 語句都能夠成功更新表的情況下,事務才會得到成功調用。為了確保兩條語句都能夠生效或都不生效,應用程序將以這樣的方式運行:直到 COMMIT 發生之前,數據庫不會做出任何更改。發生 COMMIT 時,所有未提交的語句(自最近一次 COMMIT 之後的所有語句)將同時生效,確保數據的完整性。這類似於禁用命令行處理器(CLP)的 AUTO COMMIT 行為,然後發出一組語句並手動完成 COMMIT 操作。ROLLBACK 將移除所有未提交的修改。因此 COMMIT 和 ROLLBACK 語句是事務實現的重要構建塊。
自治事務簡介
自治事務擁有自己的 COMMIT 和 ROLLBACK 范圍,確保它的結果不會影響到調用方的未提交的變更。此外,調用會話中的 COMMITs 和 ROLLBACKs 不應當影響自治事務本身完成時發生的最後更改。
注意,調用會話將被暫停,直到被調用的會話返回控制權。自治事務的支持不應該視為支持並行執行會話。
創建自治事務
在 DB2 中,自治事務通過自治過程實現。存儲過程為將語句綁定到塊中提供了一種自然的方式。要創建自治過程,需要在 CREATE PROCEDURE 語句中指定關鍵字 AUTONOMOUS,如清單 12 所示。
清單 2. CREATE PROCEDURE 語句示例CREATE OR REPLACE your_procedure_name
LANGUAGE SQL
AUTONOMOUS
BEGIN
do autonomous work ;
END
在調用自治過程時,將在獨立的會話中執行,以提供必需的事務獨立性。成功的自治過程將使用隱式方式提交,而失敗的自治過程將執行回滾。無論哪一種情況,都不會影響調用事務。
一個真實的用例
銀行 B 希望針對包含客戶敏感數據的表的每一個查詢都被正確記錄。要實現這個目標,銀行 B 的應用程序開發人員獲得了一組接口,他們可以用這些接口訪問敏感數據。每個接口被實現為一個存儲過程。存儲過程從表中返回所需的信息,與此同時,記錄發出查詢的雇員的用戶 ID 和被查詢的客戶記錄的帳戶編號,包含日期和時間。
前提條件
SQL 作出以下所有假設:
存在數據庫連接
關閉自動提交功能
語句終止符被設置為 %,方式是在啟動新的 DB2 CLP 會話時輸入 DB2 CLP 語句 db2 +c -td%
開始
首先創建必要的表。需要用一個表保存客戶敏感信息,用另一個表保存在每次訪問敏感信息時記錄的信息。清單 3 展示了一個例子。
清單 3. 創建兩個示例表 DROP TABLE customerSensitiveInfo %
CREATE TABLE customerSensitiveInfo(customerAccountNumber integer, amountOverdue integer) %
DROP TABLE log_table %
CREATE TABLE
log_table(queryingEmployeeID varchar(100),
customerAccNumber integer, when timestamp) %
COMMIT %
接下來,創建一個過程以在敏感信息被訪問時寫入到 log_table,如清單 4 所示。
清單 4. 寫入到日志表CREATE OR REPLACE PROCEDURE
log_query (in queryingEmployee varchar(100),
in accNumber integer, in when timestamp)
LANGUAGE SQL
BEGIN
insert into log_table values (queryingEmployee, accNumber, when);
END %
COMMIT %
銀行 B 為其應用程序開發人員提供的接口之一可以查詢某個給定帳戶的過期程度。過程 get_AmountOverdue 將首先對 log_query 過程發出調用,表示它將訪問敏感數據。然後從 customerSensitiveInfo 表中執行 select,獲取給定帳戶編號的過期時間量。清單 5 展示了一個例子。
清單 5. get_AmountOverdue 過程CREATE OR REPLACE PROCEDURE
get_AmountOverdue(in accountNumber integer, out overdue integer)
LANGUAGE SQL
BEGIN
DECLARE due integer;
DECLARE currentTime timestamp;
SET currentTime= CURRENT TIMESTAMP;
CALL log_query(CURRENT USER, accountNumber, currentTime );
SELECT amountOverdue INTO due FROM customerSensitiveInfo
WHERE customerAccountNumber= accountNumber;
SET overdue=due;
END %
COMMIT %
創建了 get_AmountOverdue 接口後,向 customerSensitiveInfo 表中添加一些客戶數據。接下來,執行清單 6 中的語句創建表。
清單 6. 創建示例表的語句INSERT INTO customerSensitiveInfo VALUES(12345, 10000),(12346,20000) %
COMMIT %
結果生成的表包含如表 1 所示的信息。
表 1. CustomerSensitiveInfo
CustomerAccountNumber
AmountOverdue
12345
10,000
12346
20,000
現在表中已經填充了數據,並且可以使用某種方式訪問它,那麼現在從帳戶 12345 中檢索過期時間量。由於您只對查看數據感興趣,因此希望以匿名方式執行,在調用之後立即發出一條回滾語句來隱藏您的蹤跡,如清單 7 所示。
清單 7. 向 get_AmountOverdue 代碼添加一條回滾語句CALL get_AmountOverdue(12345, ?) %
Value of output parameters
--------------------------
Parameter Name : OVERDUE
Parameter Value : 10,000
return Status = 0
ROLLBACK %
檢查 log_table 的狀態,應當如清單 8 所示。
清單 8. log_tableSELECT * FROM log_table %
QUERYINGEMPLOYEEID CUSTOMERACCNUMBER WHEN
0 record(s) selected.
如您所料,log 表現在是空的,因為包含實際表訪問和日志表插入的事務被回滾了。這不是我們希望的行為。向 log_query 過程添加 AUTONOMOUS 關鍵字,如清單 9 所示。
清單 9. 向 log_query 過程添加 AUTONOMOUS 語句CREATE OR REPLACE PROCEDURE
log_query (in queryingEmployee varchar(100),
in accNumber integer, in when timestamp)
LANGUAGE SQL
AUTONOMOUS
BEGIN
INSERT INTO log_table values (queryingEmployee, accNumber, when);
END %
COMMIT %
現在從帳戶 12345 檢索過期時間量,然後再次回滾該事務,如清單 10 所示。
清單 10. 包含回滾語句的 get_AmountOverdue 代碼CALL get_AmountOverdue(12345, ?) %
Value of output parameters
--------------------------
Parameter Name : OVERDUE
Parameter Value : 10,000
return Status = 0
ROLLBACK %
再次檢查 log_table 的狀態,現在應當如清單 11 所示。
清單 11. 添加了 AUTONOMOUS 語句之後的 log_table SELECT * FROM log_table %
QUERYINGEMPLOYEEID CUSTOMERACCNUMBER WHEN
98765 12345 2009:05:25:12.00.00.000000
1 record(s) selected.
這一次,我們獲得了理想的結果。即使讀取敏感信息的事務本身被回滾,log_table 的條目也會被提交。通過這種方式,您可以維護數據訪問歷史,即使訪問本身沒有被提交。
結束語
本文介紹了自治事務的概念。現在,您應該理解什麼是自治事務,以及如何在 DB2 內創建和使用自治事務。