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
- Mysql使用kill命令解決死鎖問題MySql
- 手把手教你分析解決MySQL死鎖問題MySql
- 故障解析丨一次死鎖問題的解決
- 死鎖問題排查過程-間隙鎖的復現以及解決
- Oracle死鎖一例(ORA-00060),鎖表導致的業務死鎖問題Oracle
- MySQL死鎖問題MySql
- Python | 淺談併發鎖與死鎖問題Python
- Python | 多執行緒死鎖問題的巧妙解決方法Python執行緒
- 記憶體混亂及解決方法和死鎖問題記憶體
- 併發技術5:死鎖問題
- MySQL 死鎖解決MySql
- MySQL解決死鎖MySql
- MySQL 死鎖問題分析MySql
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- 解決庫存扣減及訂單建立時防止併發死鎖的問題
- 用分散式鎖解決併發問題分散式
- MySQL鎖等待與死鎖問題分析MySql
- SpringBoot Seata 死鎖問題排查Spring Boot
- 線上併發事務死鎖問題排查
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- 檢視oracle死鎖程式並結束死鎖Oracle
- 從一個死鎖問題分析最佳化器特性
- MySQL死鎖分析與解決之路MySql
- JDBC Oracle executeUpdate 卡死問題解決JDBCOracle
- 解決Oracle序列跳號問題Oracle
- Oracle 自動備份觸發ORA-01513問題Oracle
- 什麼是死鎖?如何解決死鎖?
- MySQL 高階 | 用儲存過程、定時器、觸發器來解決資料分析問題MySql儲存過程定時器觸發器
- Oracle開發基礎-觸發器Oracle觸發器
- mysql慢查詢,死鎖解決方案MySql
- 例項詳解 Java 死鎖與破解死鎖Java
- 禁止oracle表的觸發器triggerOracle觸發器
- 併發:死鎖
- ORACLE賬戶提示EXPIRED(GRACE)問題解決Oracle
- Oracle:ORA-27090 問題解決總結Oracle
- JAVA死鎖排查-效能測試問題排查思路Java
- 記一次 MySQL select for update 死鎖問題MySql
- PHP利用Redis鎖解決併發訪問PHPRedis