首頁  >  文章  >  資料庫  >  圖文詳解Oracle鎖定表解決方法的詳細記錄

圖文詳解Oracle鎖定表解決方法的詳細記錄

WBOY
WBOY轉載
2022-08-17 18:13:513208瀏覽

這篇文章為大家帶來了關於Oracle的相關知識,在開發Oracle資料庫時,我們常遇到頻繁操作的Oracle資料表,會出現Oracle鎖定表,下面給大家介紹了Oracle鎖定表解決方法的相關資料,希望對大家有幫助。

圖文詳解Oracle鎖定表解決方法的詳細記錄

推薦教學:《Oracle影片教學

鎖定表或鎖定超時相信大家都不陌生,常發生在DML語句中,產生的原因就是資料庫的獨佔式封鎖機制,執行DML語句時對錶或行資料進行鎖住,直到交易提交或回滾或強制結束目前會話。

對於我們的應用系統而言鎖表大概率會發生在SQL執行慢並且沒有超時的地方(一條SQL由於某種原因(Spoon工具做資料抽取與推送)一直執行不成功並且一直不釋放資源)因此寫出高效率SQL也特別重要!還有另外情況也會發生鎖表,就是高並發場景,高並發會帶來的問題就是Spring事務會造成資料庫事務未提交產生死鎖(當前事務等待其他事務釋放鎖資源)!從而拋出異常java.sql.SQLException: Lock wait timeout exceeded;。

那麼如何解決鎖定表或鎖定逾時呢?臨時性解決方案就是找出鎖定資源競爭的表或語句,直接結束目前會話或sesstion,強制釋放鎖定資源。例如

解決方法如下:

1、session1修改某資料但不提交事務,session2查詢未提交事務的那筆記錄

2、session2嘗試修改

我們可以看到修改未提交事務的記錄會處於一直等待狀態,直到對方釋放鎖定資源或強制關閉session1。這裡也說明了Oracle做到了行級鎖!

這裡只是簡單的模擬了出現鎖定表情況,可以一眼看出就是session1導致的鎖定表。實際開發中遇到這種情況一般都是使用SQL直接查出鎖定資源競爭的表或語句然後進行資源的強制釋放! !

3、session3查詢競爭資源的表或語句,強制釋放資源

-- 查询未提交事务的session信息,注意执行以下SQL,用户需要有DBA权限才行
SELECT
    L.SESSION_ID,
    S.SERIAL#,
    L.LOCKED_MODE AS 锁模式,
    L.ORACLE_USERNAME AS 所有者,
    L.OS_USER_NAME AS 登录系统用户名,
    S.MACHINE AS 系统名,
    S.TERMINAL AS 终端用户名,
    O.OBJECT_NAME AS 被锁表对象名,
    S.LOGON_TIME AS 登录数据库时间
FROM V$LOCKED_OBJECT L
    INNER JOIN ALL_OBJECTS O ON O.OBJECT_ID = L.OBJECT_ID
    INNER JOIN V$SESSION S ON S.SID = L.SESSION_ID
WHERE 1 = 1

#查詢結果如下

對我們強制釋放資源有用的只有前面兩個字段,例如

-- 强制 结束/kill 锁表会话语法
ALTER SYSTEM KILL SESSION 'SESSION_ID, SERIAL#';

-- 强制杀死session1,让session2可以修改id=5的那条记录
ALTER SYSTEM KILL SESSION '34, 111';

強制殺死session1後,注意觀察session2的執行情況!我們會發現session2的等待會立即終止並執行!相信小夥伴們都有一個疑惑,session_id有29和34,如何確定他們屬於session1還是session2,保證殺死的是session1讓session2成功執行DML語句?

其實也很簡單,這裡的判斷方式就是session1執行更新但不提交事務,可先用以上SQL查詢未提交事務的session信息,此時查到的就是session1的信息。

推薦教學:《Oracle影片教學

以上是圖文詳解Oracle鎖定表解決方法的詳細記錄的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:jb51.net。如有侵權,請聯絡admin@php.cn刪除