2013-10-11 52 views
1

我在應用程序中間歇性地發生死鎖。我的應用程序有1個表,例如EMPLOYEE(ID(PK),NAME,SAL),並且有2個會話。SELECT FOR UPDATE中的數據庫死鎖

會議1:

SELECT ID, NAME, SAL FROM EMPLOYEE WHERE SAL= (SELECT MIN(SAL) FROM EMPLOYEE) FOR UPDATE 
Let say the query return EMPLOYEE ROW having ID=2 
then application does some processing like rs.updateInt(ID_SAL, 10); 

會話2:(對於其他業務邏輯)

SELECT ID, NAME, SAL FROM EMPLOYEE WHERE ID=2 FOR UPDATE. 

因此,在應用中兩個會話嘗試更新同一行(例如行與ID = 2)預計這種情況,因此我認爲SELECT ..FOR UPDATE將有所幫助。

我做錯了什麼?我假設SELECT FOR UPDATE會震盪行,當其他會話嘗試更新同一行時,它將等待會話1完成。

回答

4

我假設SELECT FOR UPDATE將搖滾的行,當其他 會議將嘗試更新同一行,它會等到會議1點 完成。

確切地說,但是,當您完成此行或關閉會話時,您需要關閉事務。 您的問題的一種可能的情況是下一個:

過程1個鎖與ID = 2排,更新並打算與ID = 1的下一個記錄(但會話和交易仍然活躍) 過程2已鎖定行與ID = 1和去鎖定行與ID = 2(但會話和事務仍然是活動的)

所以處理1正在等待記錄ID = 1個保持記錄ID = 2個

過程2是等待記錄ID = 2並保持記錄ID = 1

這是一個死鎖。在完成記錄後,您必須完成交易以將其釋放給其他流程。

如果您需要在一個事務中更新多個記錄,只需將它們全部鎖定在一起,並在完成工作後釋放。

+0

感謝Nicolai的快速響應。是的,你的解釋是正確的。在這兩個會話中,一旦處理完成,我會執行提交/回滾事務,即rs.updateRow()。在會話1中,我的應用程序只處理1行(注意:會話1查詢可以返回多行,但我只處理1行)。會話2查詢將始終返回1行。 –

+0

最重要的是在切換到兩個進程中的其他記錄之前,釋放(完整事務或關閉會話)記錄或大量記錄。 – Nicolai