Oracle觸發器死鎖問題解決
這兩天一直在因為系統初期設計原因導致的一個觸發器問題。
問題如下:
有表T,有客戶編號、賬戶編號及地址三個欄位(為方便起見以最少欄位描述)。
一個客戶編號下可能存在多個賬戶編號(3個或4個)。
假設客戶編號C0下有A1、A2、A3三個賬戶編號。
現在對賬戶編號A1的地址欄位進行了更新,要求透過觸發器同時更新客戶編號C0下的另外兩個賬戶A2和A3的地址欄位。
透過實際的觸發,發現存在著一個非常致命的問題:
由於指定的是自治事務觸發器(即指定了pragma autonomous_transaction),假設為T1。每次更新表時觸發都是獨立的。因此就產生了死迴圈和死鎖的問題。
因為更新了A1,則T1觸發。T1內去找到同個客戶編號下的A2和A3。然後先更新A2,此時便又觸發了T1。然後又找到同個客戶編號下的A1和A3。然後先更新A1,而由於先前第一次更新已經鎖住了A1,再次更新就會導致死鎖。因為先前的A1更新需要現在的A1先完成。而現在的A1更新卻被先前的A1更新阻塞了。
從上面可以看出,如果可以找到這樣一個辦法,將鎖住的行找出來,然後在每次更新之前都判斷一下該行是否被鎖住。如果鎖住則跳到下一條記錄進行處理。沒鎖住則繼續更新。
實際上這只是理想的情況,的確可以透過查詢v$lock v$session v$locked_object查到被鎖住的行:
select ta.account_no, o.object_name, ta.rowid
from v$session s, ttest ta, user_objects o, v$locked_object lo
where lo.SESSION_ID = s.SID
and lo.OBJECT_ID = o.object_id
and dbms_rowid.rowid_object(ta.rowid) = o.data_object_id
and o.object_id = s.ROW_WAIT_OBJ#
and dbms_rowid.rowid_relative_fno(ta.rowid) = s.ROW_WAIT_FILE#
and dbms_rowid.rowid_block_number(ta.rowid) = s.ROW_WAIT_BLOCK#
and dbms_rowid.rowid_row_number(ta.rowid) = s.ROW_WAIT_ROW#
但是透過實際除錯發現。這個記錄的並不是當時被鎖住的所有記錄。而是最後一次被鎖住的一條記錄。什麼意思呢?也就是說當時可能有幾條記錄被鎖住。但是這個SQL所查出來的是執行所有鎖行操作的語句後,最後一次被鎖住的行。也就是失去了即時判斷的可能性。
想透過另外的方法去找到這個被鎖住的行我網上也搜尋過無數遍了。都沒有實際解決方案。可能這麼做的人很少吧。
最後想到了一個辦法,就是透過臨時表的方法去記錄被更新的行。一旦觸發T1,就往臨時表記錄這一行的rowid和對應的鎖定標識。然後在更新的時候判斷
是否已經存在於該表中。如果有則不更新,沒有則往下更新。更新並提交後該行
鎖標識清零。進入下一次迴圈。
這個臨時表是會話級的。因此在觸發器迴圈觸發過程中都是處於同一個資料環境下。方便了對指定行的加鎖與解鎖(其實是設定行鎖定狀態)。
下一篇準備講述此次解決死鎖問題而學習到的關於Oracle鎖的一些方面的知識。
(備註:如果不指定自治事務觸發器,則無法修改觸發器觸發所在的表)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12932950/viewspace-607691/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 解決Oracle死鎖問題步驟Oracle
- 由Oracle觸發器死鎖及行級鎖限制所衍生的解決方案Oracle觸發器
- oralce觸發器解決問題觸發器
- oracle變異表觸發器相關問題解決Oracle觸發器
- SQLserver 程式被死鎖問題解決SQLServer
- Mysql使用kill命令解決死鎖問題MySql
- 通過 sysprocesses 解決Sql死鎖問題SQL
- Oracle 解決鎖表問題Oracle
- oracle 鎖問題的解決Oracle
- Java 程式死鎖問題原理及解決方案Java
- 解決SQL2005死鎖問題SQL
- 手把手教你分析解決MySQL死鎖問題MySql
- 解決Oracle死鎖的快捷方法Oracle
- oracle死鎖測試與解決Oracle
- 解決Oracle資料庫死鎖Oracle資料庫
- oracle觸發器~ 更新多表的問題Oracle觸發器
- SQ死鎖及死鎖的解決
- 故障解析丨一次死鎖問題的解決
- 死鎖問題排查過程-間隙鎖的復現以及解決
- ORACLE ERP解決死鎖的方案Oracle
- oracle 死鎖解決方法一例Oracle
- MySQL死鎖問題MySql
- 利用觸發器解決更新主鍵衝突的問題觸發器
- 併發技術5:死鎖問題
- MySQL 死鎖解決MySql
- SQL Server 2000 死鎖(dead lock) 問題解決SQLServer
- 一個ORACLE死鎖問題的追蹤Oracle
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- Python | 淺談併發鎖與死鎖問題Python
- oracle 臨時表 解決 "表 *** 發生了變化,觸發器/函式不能讀"的問題Oracle觸發器函式
- oracle 死鎖表解決方法Oracle
- Oracle資料表死鎖的解決方法Oracle
- Oracle資料庫DDL審計觸發器觸發的bug問題Oracle資料庫觸發器
- ORACLE觸發器詳解Oracle觸發器
- MySQL 死鎖問題分析MySql
- Sqlserver分析死鎖問題SQLServer
- 線上死鎖問題分析
- 死鎖問題總結