從理想的角度來說,如果能對記錄進行鎖定,則會給多用戶程序帶來極大的靈活性。然而遺憾的是,MicrosoftJet引擎不支持真正的記錄鎖定,而是使用頁面鎖定。頁面鎖定只鎖定包含當前正在編輯的記錄的頁,MicrosoftJet進行訪問和鎖定的頁的大小為2K(2048個字節)。在使用頁面鎖定時,其他用戶可以讀取鎖定頁中的數據,但不能對數據進行修改。在這種鎖定方案中,每次將鎖定多個記錄,鎖定的記錄的個數取決於每個記錄的大小。例如,如果每個記錄的長度為230個字節,則每次只能鎖定9個記錄;而如果記錄的長度為30個字節,則每次可鎖定68個記錄。
鎖定模式。頁面鎖定分為兩種模式,即保守式鎖定和開放式鎖定,它確定了MicrosoftJet如何對數據進行鎖定。當編寫在頁面級別上鎖定數據的應用程序時,必須確定要使用哪種鎖定模式。頁面鎖定可以通過兩種方法來設置,即LockEdits屬性和OpenRecordset方法中的lockedit5參數。
1.用LockEdits屬性指定鎖定模式。鎖定模式可以通過LockEdits屬性來指定。該屬性可用於各種Recordset對象,包括動態集、快照、表及動態類型的Recordset對象。LockEdits屬性是一個布爾值,當把該值設置為True(缺省)時,將對記錄集進行保守式鎖定,即在執行Edit方法時鎖定2K的頁面:如果把該屬性設置為False,則對記錄集進行開放式鎖定,即在執行UPdate之前不鎖定要更新的記錄所在的2K頁面。如下面的例子:
DimrstTemPAsReCordset
……
rstTemp.LockEdits=True
說明:a.鎖定頁面後,其它用戶不能對正在編輯的記錄所在頁面進行修改,但可以讀取鎖定頁中的數據。在其它用戶鎖定頁面後,如果再把LockEdits屬性設置為True,則會出錯。b.如果把LockEdits屬性設置為False,且其它用戶已鎖定頁面,則其後的用戶在使用Update時將會出錯。c.當與Microsoft連接的ODBC數據源一起操作時,LockEdits屬性被設置為False,即開放式鎖定。
2.用OpenRecordset方法指定鎖定模式。我們已多次使用過OpenRecordset方法,該方法的格式如下:
Setrecordset=object.OpenRecordset(type,options,lockedits)
其中第三個參數,即lockedits,用來指定鎖定模式或以只讀方式打開記錄集。該參數可以取以下5種值:
(1)dbReadOnly:以只讀方式打開記錄集。注意,在options參數中也可以使用dbReadOnly,但不能同時使用,否則會產生錯誤。
(2)dbPessimistic:用保守式鎖定模式打開記錄集,一旦使用Edit方法,將立即鎖定正在編輯的記錄所在的頁面,直到執行Update方法後才釋放對該頁面的鎖定。
(3)dbOptimistic:用保守式鎖定模式打開記錄集,在執行Update方法前不鎖定正在編輯的記錄所在的頁面。
(4)dbOptimisticValue:基於行值使用開放式並發(僅ODBCDirect工作區)。
(5)dbOptimisticBatch:允許開放式更新(僅ODBCDirect工作區)。
保守式鎖定和開放式鎖定。
1).保守式鎖定。保守式鎖定也稱為悲觀鎖定。設置保守式鎖定後,只要對某個記錄使用Edit方法,就自動鎖定該記錄所在的頁面,直到顯式地提交或取消這個記錄的變更(例如執行UPdate方法)後,才釋放對該頁面的鎖定,並把數據寫入文件中。保守式鎖定是Recordset對象的缺省鎖定方式。保守式鎖定的主要優點是,獲得鎖定之後,只要記錄還被鎖定著,就可以防止其它用戶修改該記錄中的數據,因此不會發生任何鎖定沖突。另外,由於一個用戶不能在另一個用戶開始編輯記錄之後改變它,所以,保守式鎖定也是保證應用程序讀取最新數據的唯一方法。保守式鎖定的缺點是,在編輯和鎖定該記錄的過程中,包含該記錄的整個頁面都被鎖定。當鎖定時間較長時,可能會給其它用戶造成不必要的麻煩。例如,用戶設置保守式鎖定後,開始編輯一個記錄,並在記錄被鎖定期間離開了計算機(例如出去辦事),這不僅鎖定了用戶正在編輯的記錄,而且鎖定駐留在該鎖定頁面內的其它記錄,使其它用戶長時間內無法編輯頁面中的記錄。
2).開放式鎖定。開放式鎖定也稱樂觀鎖定。使用開放式鎖定時,MicrosoftJet引擎僅在試圖用Update方法提交記錄變更時才鎖定頁面,完成更新操作後立即釋放對頁面的鎖定。由於鎖定僅在應用程序試圖提交變更時發生,因此能使鎖定的時間最短,使其它用戶只在鎖定生效的較短時間內不能訪問該頁面。這是開放式鎖定的主要優點。開放式鎖定的缺點是:當用戶正在編輯記錄時,不能保證更新是否會成功。如果另一個用戶改變了第一個用戶正在編輯的記錄,那麼依賴於開放式鎖定的更新將會失敗。例如,假定張三和李四正在編輯同一個記錄,張三開始以開放式鎖定編輯某個客戶記錄。由於張三使用的是開放式鎖定,並沒有真正鎖定記錄,所以不能禁止李四試圖編輯相同的記錄。在李四編輯相同的客戶記錄時,他不知道張三正在編輯該記錄,並且也沒有看到最新的數據。當張三試圖在李四編輯相同的客戶記錄時存儲他的變更,就會產生一個錯誤。對於大多數數據庫應用程序來說,可能要選擇開放式鎖定,因為其它用戶修改或刪除本人正在使用的記錄的可能性要小於試圖訪問已被鎖定的頁面上記錄的可能性。但是,如果某個應用程序中有多個用戶同時訪問和編輯記錄,則應使用保守式鎖定,以確保在執行編輯期間記錄不被其他人修改。在這種情況下,應注意不要使記錄鎖定的時間過長。
3).釋放鎖定。如前所述,在執行Update方法後,將自動釋放頁面鎖定。但是,釋放記錄鎖定是一種後台進程,有時候,其它操作發生得很快,以至於數據庫來不及處理該進程。如果正在開發一個數據輸入密集型的應用程序,則可能需要暫停應用程序的處理,這可以通過MicrosoftJet數據庫引擎的Idle方法來完成。Idle方法掛起數據處理,啟用MicrosoftJet數據庫引擎執行其它操作,諸如內存優化或內存頁超時等(僅MicrosoftJet工作區)。該方法用於DBEngine對象,格式如下:
DBEngine.Idle[dbRefreshCachel
在多用戶環境中,用Idle方法可以使MicrosoftJet數據庫引擎執行後台任務。在一般情況下,僅當沒有任何操作(包括移動鼠標)發生時,才釋放讀鎖定並更新本地動態集類型的Recordset對象中的數據。如果定時地使用Idle方法,則MicrosoftJet可以釋放不必要的讀鎖定,以捕獲後台處理任務。Idle方法有一個可選的參數,即dbRefreshCache,如果使用該參數,則可強制掛起寫入.MDB文件,並用.MDB文件中的最新數據刷新內存。->