2017-02-18 27 views
0

我想知道是否有可能一次將數據庫表鎖定給一個用戶,以便在數據庫上執行ACID術語,並允許一個完整事務處於在Microsoft Access數據庫中使用VBA的時間。我正在尋找僞代碼中的以下內容:將數據庫表一次鎖定到一個用戶在Microsoft Access中VBA

  • 鎖定所有表(或某些表)。
  • 執行所有SQL或其他內部操作。
  • 執行交易並解鎖所有表格(或某些表格)。

但是,在客戶端故障的情況下,例如,客戶端應用程序掛起並且用戶必須在客戶端應用程序仍在處理事務時強制關閉它,它將恢復更改並且從不實際執行事務,並解鎖該鎖。我正在尋找的是一個READ和WRITE鎖,而試圖鎖定數據庫的客戶端在它已經被鎖定的時候,它將不得不等待,直到它被解鎖?

Dim wks  As DAO.Workspace 
Dim dbs  As DAO.Database 

Set wks = DBEngine(0) 
Set dbs = wks.Databases(0) 

wks.BeginTrans 
    ' Do stuff using dbs and DAO. 
wks.CommitTrans 

Set dbs = Nothing 
Set wks = Nothing 

如果錯誤是可能的,包括跳過CommitTrans和調用錯誤處理程序:

+0

這是你想要的開始http://stackoverflow.com/questions/5792169/opening-access-database-in-exclusive-mode#answer-5792773 –

回答

1

工作區的事務中包裝你的交易

wks.RollBack 
+0

但這並不妨礙閱讀。我曾嘗試過! – falhumai

+2

你應該在你的問題中提到,爲什麼你認爲這並不能解決你的問題。目前還不清楚爲什麼其他用戶在交易運行時不應該有讀權限。 ACID(雖然Access沒有完全遵守它)保證數據庫中不存在不一致的狀態:或者事務成功完成,或者根本不完成。兩者之間沒有任何關係。在另一個用戶的交易中同時閱讀是ACID保證的核心功能。 – Leviathan

+1

@Leviathan是對的。如果用戶有權訪問該文件,則無法阻止閱讀。閱讀是可能的最低訪問級別。如果實際上沒有用戶正在使用數據庫,則只能阻止訪問;第一個用戶可以獨佔打開該文件(您可以將其稱爲_single user mode_)。然後沒有其他用戶可以打開數據庫。然而,這不能在VBA中完成 - 它由命令行控制。 – Gustav

0

其實,我找到了一種方法通過構建的哈克鎖類型來模擬單個用戶的讀寫訪問。以下將描述我是如何實現它的。

因此,我在訪問中創建了一個小表,名爲Lock,並且有一列名爲SomeValue。這個列必須是一個主鍵,並且可以是任何值,所以我把它作爲類型編號。該表將存儲所有將在其中創建的鎖,並且試圖獲取該鎖的兩側必須同意該鎖的值。例如,兩個客戶端將嘗試獲取值爲1的鎖,因此他們應該請求鎖1,並釋放鎖1。

首先,這裏是我做了設置和解除鎖定,通過將鎖定值的雙方試圖獲取它的兩個輔助查詢:

SetLock查詢:

INSERT INTO Lock (SomeValue) 
VALUES ([GetLockValue]); 

RELEASELOCK查詢:

DELETE * 
FROM Lock 
WHERE SomeValue=[GetLockValue]; 

然後,這裏是TrySetLock功能(這將嘗試設置的值傳遞的鎖,並返回結果集,其中1是一通,0是一個發IL)和SetLock子(這會等到由價值傳遞是空的,以獲取它的鎖 - 它使用鎖定取得自旋鎖法):

Public Function TrySetLock(LockValue As Integer) As Integer 
    Dim dbs As dao.Database 
    Dim qdf As dao.QueryDef 
    Set dbs = CurrentDb 
    Set qdf = dbs.QueryDefs("SetLock") 
    qdf.Parameters("GetLockValue").Value = LockValue 
    qdf.Execute 
    TrySetLock = qdf.RecordsAffected 
End Function 

Public Sub SetLock(LockValue As Integer) 
    Do While TrySetLock(LockValue) = 0 
    Loop 
End Sub 

這裏是RELEASELOCK子(這將釋放在價值傳遞的鎖 - 此分將始終成功,即使沒有這樣的鎖存在):

Public Sub ReleaseLock(LockValue As Integer) 
    Dim dbs As dao.Database 
    Dim qdf As dao.QueryDef 
    Set dbs = CurrentDb 
    Set qdf = dbs.QueryDefs("ReleaseLock") 
    qdf.Parameters("GetLockValue").Value = LockValue 
    qdf.Execute 
End Sub 

正如你可以看到這裏,我已經使用SQL和微軟的主鍵屬性的幫助訪問表以確保插入(或通過鎖定引用)只能一次成功執行某一方或客戶端,並且不會成功執行另一方,除非第一面刪除(或釋放)鎖定雙方同意的鎖定值。

但是,如果一個客戶端未能釋放鎖(例如客戶端程序被凍結,並且不得不強制終止程序),則會阻塞所有依賴同一鎖的客戶端。我想知道當一個程序被迫被殺死或者不會被調用時,類模塊的析構函數是否會被調用?如果它被調用,那麼我認爲通過創建具有某個值的鎖類可以解決此問題,並且該類的釋放器將釋放該鎖,而不必讓其他客戶端等待該特定的鎖。

相關問題