2013-04-25 141 views
1

我有兩個運行在不同會話中的Oracle查詢,這些查詢是死鎖的,而且我很難看到爲什麼會發生這種情況。這些查詢爲什麼會死鎖?

在會話1的查詢是這樣的:

UPDATE REFS R SET R.REFS_NAME = :B2 WHERE R.REFS_CODE = :B1 

查詢在會話2是這樣的:

UPDATE REFS R SET R.STATUS_CODE = :B3, R.STATUS_TYPE = :B2 WHERE R.REFS_CODE = :B1 

每一個由通過選擇主鍵值的循環的光標所包圍。當這些查詢同時運行時,它們會死鎖。 REFS_CODE是主鍵,Oracle跟蹤顯示他們正在更新不同的rowid。主鍵被索引,很明顯,還有一些外鍵約束,這些約束由索引支持,因爲這對我們過去是一個問題。移動到絕望的境界,我試着禁用桌面上的觸發器,但沒有幫助。也嘗試使用自主交易,但這使事情變得更糟。

有什麼我失蹤了嗎?謝謝你的幫助!

+1

只有切線:但爲什麼你使用遊標,而不是隻更新你想要的行的範圍(也許使用類似第二個答案在這裏:http://stackoverflow.com/questions/2446764/oracle-update-statement-與-內加入)? – siride 2013-04-25 22:12:52

+0

你有什麼樣的交易? – Marvo 2013-04-25 22:13:55

+0

@Marvo不知道該如何回答!通常的那種?他們不AUTONOMOUS_TRANSACTIONs,如果這就是你問:) – Kieran 2013-04-25 22:14:43

回答

3

如果在整個遊標批次更新後發生提交,那麼它可能只是一個直接的死鎖場景,其中兩個遊標在相同的行上操作,但順序不同。

  • 假設session 1cursor set 1,並依次嘗試提交之前更新refs_code 1refs_code 2
  • 假設session 2cursor set 2,並且在嘗試提交之前按此順序更新refs_code 2refs_code 1

然後,交織的更新:

time cursor set 1 cursor set 2 
==== ============ ============ 

t1 refs_code 1  - 
t2 -    refs_code 2 
t3 refs_code 2  - 
t4 -    refs_code 1 

在t3,cursor set 1正在等待cursor set 2提交refs_code 2 在t4,cursor set 2正在等待cursor set 1提交refs_code 1

兩個交易等待不同的rowid。如果是這種情況,您可以在兩個光標上添加一個order by(以相同的方向)以避免這種情況。

+0

謝謝,這是問題!一個錯誤導致會話1和會話2更新相同的記錄。現在他們是單獨的列表,死鎖就消失了。 – Kieran 2013-04-26 14:03:51