18.3.2.2 使用隱式控制
在缺省情況下,Delphi通過BDE為應用程序提供隱式事務控制。當應用程序處於隱式事務控制時Delphi為DataSet中的寫每個記錄進行隱式事務控制。它提交每一個獨立的寫操作,如Post和Append Record。
使用隱式事務控制是容易的,它保證最小的記錄更新沖突和數據庫的一致性視圖。另一方面,因為寫入數據庫的數據的每一行都要進行事務控制, 所以隱式事務控制將導致網絡過忙和應用程序性能下降。
如果采用顯式事務控制,就能選擇最有效的時機來開始、提交和終止事務,特別是在開發多用戶環境下的客戶應用程序運行訪問遠程SQL服務器,就更應該采用顯式控制。
18.3.2.3 使用顯式事務控制
有兩種協作又獨立的方式可運用於Delphi數據庫應用的事務控制:
● 使用TDatabase部件的方法和屬性
● 使用TQuery部件中的傳遞式SQL。這種方式只有在Delphi Client/Server Suite版中才有效,SQL Links將SQL表達式直接傳給過程SQL或ODBC服務器
使用TDatabase部件的方法和屬性的好處是提供了清晰的、輕便的、與特定數據庫或服務器無關的應用能力。
使用傳遞式SQL的主要好處在於可以運用特定服務器的先進事務管理能力。
1. 使用TDatabase的方法和屬性
下表中列出了TDatabase部件中用於事務管理的方法和屬性以及它們的使用方法:
表18.11 TDatabase用於事務顯式控制的方法表
━━━━━━━━━━━━━━━━━━━━━━━━
方法或屬性 作 用
────────────────────────
Commit 提交數據的修改並終止事務
Rollback 取消數據的修改並終止事務
StartTransaction 開始一個事務
TransIsolation 表述事務的獨立性級別
━━━━━━━━━━━━━━━━━━━━━━━━
StartTransaction,Commit和Rollback是供應用程序在運行時調用開始事務,控制事務並且保存或放棄所做數據修改的方法。
TransIsolation是TDatabase部件的用於控制作用於相同表的不同事務之間如何交互的屬性。
⑴ 開始一個事務
當你開始一個事務時,後來的所有讀寫數據庫的表達式都發生在那次事務的環境中。每個表達式都是其中一部分。任何表達式所做的修改,要麼成功地提交給數據庫,要麼每一個修改都被取消。考慮一個在ATM上的銀行傳輸問題。當顧客決定將錢從存款帳戶轉到支付帳戶時,在銀行數據庫記錄上必須發生兩個修改:
● 存款帳戶必須記入借方
● 支付帳戶必須記入貸方
如果出於某種原因,其中的一個操作不能被完成,那麼任何一個操作都不應該發生。因為這些操作是相關的,它們應該發生在同一個事務中。
為了開始Delphi應用程序中的一個事務,需要調用TDatabase部件中的StartTransaction方法:
DatabaseInterBase.StartTransaction;
此後的所有數據操作都發生在最近一個事務的環境中,直到該次事務通過調用Commit或Rollback顯式地終止為止。
那麼,應當將事務保持多久呢?理想狀態下,只要需要,多久都行。事務的活躍狀態越長,同時訪問數據庫的用戶越多,在你的事務的生命其中,更多的並發、同時的事務開始和終止,於是當試圖提交修改時,與其它事務沖突的可能性更大。
⑵ 提交一個事務
為了做永久性修改,事務必須使用TDatabase部件的Commit方法提交。執行提交表達式將保存數據庫的修改並終止事務。例如,下列表達式將終止在上例中開始的事務:
DatabaseInterBase.Commit
Commit的調用應當置於try…except表達式中。如果一個事務不能成功提交,你就能處理錯誤,並重試操作。
⑶ 返轉一個事務
為了取消數據庫修改,必須用Rollback方法返轉一個事務。Rollback 復原一個事務的修改,並終止事務,例如:下列表達式將返轉一個事務:
DatabaseInterBase.Rollback;
Rollback通常發生在:
● 異常處理代碼
● 按鈕或菜單事件代碼,如用戶點按了Cancel按鈕
⑷ 使用TransIsolation屬性
TransIsolation屬性描述TDatabase部件事務的獨立級別,事務的獨立級別決定了事務與其它作用於相同表的事務是如何相互作用的。在改變或設置TransIsolation 的值之前,應當相當熟悉Delphi中的事務和事務管理。
TransIsolation的缺省值是tiReadCommitted。下表中總結了TransIsolation的可能值並描述了它們的含義:
表18.12 TransIsolation屬性值的含義
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
獨立級別 含 義
──────────────────────────────────────
tiDirtyRead 允許讀由其它同時事務寫入數據庫的未提交的修改。未提交的
修改不是永久性的,可能在任何時候被復原。 在這個級別你
的事務與其它事務所做的修改具有最低獨立度。
tiReadCommitted 只允許讀由其它同時事務提交的數據庫修改。這是缺省的獨
立級別。
tiRepeatableRead 允許單個的數據庫讀事務無法看見其它同時事務對相同數據做
的修改。這個獨立級別保證了你的事務一次讀一個記錄,記錄
的視圖不會改變, 在這個級別你的事務與其它事務做的修改完
全獨立。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
各種數據庫服務器不同程度地支持這些獨立級別,有的根本不支持。 如果請求的隔離級別不被服務器支持,Delphi將采用更高的獨立級別。各種服務器支持的獨立級別請參見表18.10。
如果應用程序使用ODBC與服務器交互,ODBC驅動程序必須支持獨立級別。
2. 使用傳遞式SQL
為了能使用傳遞式SQL控制事物,必須:
● 使用Delphi Client/Server Suite
● 安裝正確的SQL Links驅動程序
● 正確配置網絡協議
● 訪問遠程服務器上數據庫的能力
● 用BDE配置工具將SQLPASSTHROUGH MODE設置為NOT SHARED
通過傳遞式SQL,你可以使用TQuery、TStoredProc、或TUpdateSQL部件直接發送一個SQL事務控制表達式給遠程數據庫服務器;BDE本身並不處理SQL表達式,采用傳遞式SQL可使用戶直接獲得SQL服務器提供了事務控制優點,尤其是當那些控制是非標准的時。
SQL PASS THROUGHMODE 描述BDE和傳遞式SQL是否共享相同的數據庫聯接。在大多數情況下,SQLPASSTHROUGHMODE被設置SHARED AUTOCOMMIT。然而,如果你想將SQL事務控制傳遞給服務器,你就必須用BDE配置工具,將BDE的SQLPASSTHROUGHMODE 設置為NOT SHARED。此外,還必須為傳遞SQL事務控制表達式的TQuery部件建立獨立的TDatabase 部件。
3. 使用本地事務
BDE還支持Paradox和dBASE上的本地事務。從代碼角度而言,在本地事務和遠程數據庫服務器的事務之間沒有什麼差別。
當作用於本地數據庫表的事務開始時,更新操作被記錄在日志中,每個日志記錄包含舊的記錄緩沖區。當事務處於活躍狀態,更新的記錄被鎖定,直到事務被提交或返轉,在返轉過程中,舊的記錄被應用於將更新的記錄恢復到原先的狀態。