2016-08-30 21 views
-1

假設我們有一個表一個與領域時間:日期狀態:整數playerId:整數服務器ID:整數的Oracle SQL更新仔細檢查鎖定

我們的制約因素時間,playerid和服務器ID(UNQ_TIME_PLAYERID_SERVERID

在一段時間內,我們嘗試更新表A與新的狀態和日期的所有行:
更新狀態= 1,時間= SYSDATE其中服務器ID = XXX和狀態!= 1和時間> SYSDATE

問題,有在單獨的機器,可以在相同的SYSDATE執行相同的更新兩個分離的過程。

UNQ_TIME_PLAYERID_SERVERID違規發生!

有沒有可能強制Oracle檢查具體更新之前的原因(何時鎖定行獲取)?

我不希望使用任何「選擇更新」事情

+0

爲什麼這是一個問題嗎?只要抓住錯誤並忽略它。 –

+0

我不想簡單地忽略錯誤。對的,這是可能的。但我想知道實際上是否有可能編寫更新,該錯誤根本不會出現。 –

+0

你不能。在您得到肯定回答後,表格(行)可以被鎖定。做這種事情的唯一可靠方法就是嘗試抓住。 – Serg

回答

0

如果它的真正的時間相同的更新100%,那麼就捕獲異常而忽略它。

如果你想防止首先發生錯誤,你需要實現一些邏輯來防止第二個更新語句執行。

我可以想到一個「鎖定表」就是爲了這個目的。創建一個表TABLE_A_LOCK_TB(基於管理的原因,根據您希望存儲的信息添加列,例如設置鎖的用戶或時間戳等)。

在您對錶A執行更新語句之前,只需向TABLE_A_LOCK_TB插入一行即可。更新成功後,刪除所述行。

在對錶A執行任何更新語句之前,只需檢查TABLE_A_LOCK_TB是否有數據集。如果它不是你的更新是好的,如果它沒有,你不執行更新。

爲了簡化這個過程,您可以通過插入/刪除TABLE_A_LOCK_TB中的一行來編寫一個用於「鎖定」和「解鎖」表A的包。還要執行一個功能來檢查「鎖定狀態」。

如果您需要多個表的邏輯,您還可以通過在TABLE_A_LOCK_TB中保存表名並進行檢查來使其成爲動態的。

在應用程序中的邏輯,你可以處理這樣便(僞)每一次更新:

IF your_lock_package.lock_status(table_name) = false THEN 

    your_lock_package.set_lock(table_name); 
    -- update statement(s) 
    your_lock_package.release_lock(table_name); 

ELSE 
    -- "error" handling/information to user + exit