2007年3月12日

ADO.NET 2.0 的並行控制與資料存取衝突偵測

此文轉自http://j2se.myweb.hinet.net/

日前台灣高鐵及其系統包商所開發的訂票系統,曾出現大量重複訂位之情形,產生了車次、時段與路程都一模一樣的重複序號。類似此種訂票系統除了可使用 Web-based 架構外,若考量到斷線的處理作業,是否能在斷線的情況下還能夠交易,那麼還可考慮 client-server 的架構,如此一來就要設計各個 client side 可以配給的車號、數量,以及恢復斷線後再同步的機制,才能夠即時處理並儘可能避免重複劃位的現象。

若要避免產生重複劃位,較簡單的做法是採用 Transaction (ADO.NET) 寫法。讓某位訂票者在交易座位 1A 時,其他人都無法讀取此 1A 座位,一直到他的交易結束為止,亦可搭配使用 dirty read 去強行讀取;類似資料庫的「獨占鎖定 (exclusive lock)」,讓某人修改資料時其他人連讀取都不行 (亦會限制同時線上數量)。此種「獨占鎖定」類似 ADO.NET 的「封閉式 (悲觀) 並行存取」機制,雖然會長時間從資料被讀取開始即將其鎖定,但至少可保證交易一定有效。像這種資料 lock 的機制只要撰寫 Transaction 程式,或是調整資料庫的鎖定策略、鎖定提示就可做到。此外還可搭配使用資料庫的 TimeStamp 計數器,判斷資料列中的任何值是否有任何改變。另外 SQL Server 2005 還有更優越的 Snapshot Isolation 快照隔離模式,其提供一種新的隔離層級,可將寫入程序、讀取程序作適當地隔離,使得讀取動作不等待寫入動作、寫入動作不干擾讀取動作,以提高資料的可用性、加快交易的執行速度。

至於 ASP.NET 2.0 / Visual Studio 2005 亦提供了入門級的解決方案,可由 SqlDataSource 等資料存取控制項的圖形設定介面中,勾選「進階」按鈕內的「使用開放式並行存取」選項,即可啟動衝突偵測機制 (ConflictDetection 屬性)。此舉會將控制項預設的「OverwriteChanges」改為「CompareAllValues」,並判斷資料從剛才第一次讀取到更新的這段期間內,是否曾被其他程序變更過,此一選項亦即 ADO.NET 的「開放式 (樂觀) 並行存取」機制,只有當資料正在修改時才會進行鎖定,並在修改完後再對各個欄位的新舊資料進行比對,看是否曾在這段期間內搶先被其他使用者修改了同一筆記錄;但其他所有使用者仍可在此時去讀取,類似於資料庫的「共用鎖定 (shared lock)」。若未勾選「使用開放式並行存取」此一選項時,即會採用預設的「後進先寫入」機制,這種做法也是只在修改時才會鎖定,但不會將更新後的資料與原始資料作比對,因此有可能發生欲修改的資料被其他使用者覆寫掉之情形。

沒有留言: