2015-04-28 83 views
5

我被要求實施「訪問策略」,以限制直接連接到應用程序(不是web應用程序)的應用程序的併發執行的數量數據庫。限制使用數據庫的應用程序進程的併發執行

應用程序在多臺機器上運行,如果多於一個用戶試圖調用該進程,則在給定時間只允許執行一次執行,另一次必須返回錯誤消息(不等待第一次執行結束)。

雖然我使用的是Java/Postgres,這是一個普遍的問題。

鑑於我有幾臺機器運行相同的應用程序,我能想到的最簡單的解決方案是實現某種「數據庫標誌」。

喜歡的東西檢查過程當前是否處於活動:

SELECT Active FROM Process 

如果它是積極的,返回一個「併發訪問策略錯誤」。如果不是,將其激活:

UPDATE Process SET Active = 'Y' 

一旦執行完畢,只需更新活動標誌:

UPDATE Process SET Active = 'N' 

不過,我遇到了一個大問題:

  • 如果我不要使用數據庫事務來更改活動標誌,並且應用程序被終止,活動標誌將永遠保持Y值。
  • 如果我使用數據庫事務,第一點就解決了。但是,主機中的活動標誌(從N到Y)的更改僅在提交後纔可見,因此其他主機將永遠不會以Y值讀取活動狀態,因此無論如何都會執行。

任何想法?

+0

只需稍加思考:您可以在單獨的事務中設置標誌(可能結合顯式鎖定),或者您可以查看對某種羣集範圍鎖定進行榛樹播放(儘管這可能會對您的應用程序造成影響)。 – Marvin

+0

與問題沒有直接關係,但是您可以使用'INSERT'而不是'UPDATE'來獲益。當第一個用戶調用該進程時,應該在數據庫中插入一個新行。當第二個用戶調用該進程時,他使用相同主鍵的'INSERT'應該失敗。 – CKing

回答

1

不要打擾一個活動的標誌,而是簡單地根據用戶ID鎖定一行。保持該行鎖定在專用的交易/連接中。當其他用戶試圖鎖定該行時(使用SELECT ... FOR UPDATE),您將看到一個錯誤,並且您可以報告它。

如果持有該事務的進程失敗,則該鎖被釋放。如果退出,該鎖被釋放。如果數據庫重新啓動,則該鎖被釋放。

贏得全場。

+0

是的!絕對是最簡單,最直接的解決方案。完美的作品。爲了完成解決方案,我必須在SELECT ... FOR UPDATE中使用NOWAIT選項,以便在第二個進程嘗試獲取鎖定時獲取異常。非常感謝!! –

1

而不是隻有一個簡單的Y/N標誌,把時間戳設置爲活動,並讓您的客戶端應用程序定期(例如每分鐘或每五分鐘)設置一次。然後,如果客戶崩潰,其他客戶將不得不等待超過該時間限制,然後假定客戶已經死亡並接管。這只是某種「心跳」機制,用於檢查啓動該過程的客戶端是否還活着。

一個更簡單的解決方案是將數據庫配置爲只接受一個連接?

1

我不確定RDBMS是否是解決此類問題的最佳系統。但我最近在SQL Server 2012中實現了類似的東西。所以這就是我從那次經歷中學到的東西。通常,我的意思是,原則上,您需要一個原子操作「檢查該值,更新(單個記錄的)值」,即原子SELECT/UPDATE。這使事情變得複雜。由於通常RDBMS中沒有這種標準的單一原子操作,因此您可以熟悉並使用ISOLATION LEVEL SERIALIZABLE

這是我在SQL Server 2012中實現它的方式,並且我已經認真測試過它,它工作正常。我有一個名爲DistributedLock的表,它的每條記錄表示一個邏輯鎖。我允許的操作是tryLockreleaseLock(這些實現爲兩個存儲過程)。 tryLock是非阻塞的(實際上是非阻塞的)。如果成功,它會向呼叫者返回一些ID /戳記,稍後可以使用該ID /戳記來呼叫releaseLock。如果在沒有實際持有鎖的情況下(沒有最新的ID /標記)呼叫releaseLock,則呼叫成功並且不執行任何操作,否則(如果主叫方有鎖),呼叫成功並釋放主叫方持有的鎖。我也支持超時。因此,如果某個進程獲取給定鎖定/記錄的ID /戳記,並忘記釋放它,則會在一段時間後自動失效。

下面是表格的樣子。

[DistributedLockID] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL -- surrogate PK 
[ResourceID] [nvarchar](256) NOT NULL -- resource/lock logical identifier 
[Duration] [int] NOT NULL 
[AcquisitionTime] [datetime] NULL 
[RecordStamp] [bigint] NOT NULL 

我想你可以找出其餘的(或嘗試,然後ping我,如果你卡住了)。

+0

+1並感謝您的詳細解釋。我簡單地將Will Hartung標記爲正確的答案,因爲這是一個非常簡單而有用的Postgres解決方案。 –

相關問題