簡露一手-一次大型業務系統的突發故障-有必要知道一點點Oracle鎖故

amadan發表於2021-09-09

複雜的故事簡單說,複雜的問題簡單做,您好,這裡是簡露一手,歡迎瀏覽。

簡述


16-7月,一大型線上業務系統伺服器突然一個個掛掉,重啟後不到撐不到五分鐘就犧牲,導致生產系統業務故障圖片描述oracle鎖

定位


因所有應用都有問題,且在未釋出版本情況下突然發生,預備進行三個步驟排查定位。

  • 檢查資料庫情況.

  • 檢查伺服器日誌.

  • 檢查伺服器網路情況.

資料庫情況

這裡不說其它的檢查項,直奔這次事因:“資料庫鎖”

根據經驗,我們進行了資料庫的檢查,幸運的是直接找到了問題點。
有一個業務表鎖的數量超過100,根據sql_id找出了所有sql,發現了全表鎖和鎖全表語句,是一條更新全表的update語句。

查詢鎖:
select object_name as 物件名稱,s.sid,s.serial#,p.spid as 系統程式號,s.SQL_ID from v$locked_object l , dba_objects o , v$session s , v$process p where l.object_id=o.object_id and l.session_id=s.sid and s.paddr=p.addr;
查詢鎖表的語句:
select * from v$sql where sql_id='65gmqgahz6jp8'

處理


鎖一旦出現 ,最簡單的辦思路就是殺[kill]。
kill 分兩種:

  • oracle 命令kill
    ALTER SYSTEM KILL SESSION 'sid,serial#';

  • 後臺殺oracle語句kill
    kill -9 spid

sid,serial#,spid 取值於 查詢鎖查詢結果。

開始殺

首殺

使用[oracle 命令]kill後 新的鎖又多了起來,改用[後臺殺]kill後,新的鎖仍在繼續。

再查

分析鎖全部的update語句會話是oracle自己產生的,來源於儲存過程的機率比較大,在排查儲存過程中找到了它,並根據它找到了一個job,是job的重複執行 導致了全表鎖的不斷產生。

二殺

刪除job後重新kill,第二次殺程式後,情況並沒有好轉,沒有了全表鎖,但是行鎖仍然多,問題變得更為複雜。

再查

經過漫長的分析百種嘗試,最終找到來問題.這是一個大意遺漏的點。生產機器一般做了rac,有多個例項,透過tns連線過去的會話一直在一個例項上,檢視鎖情況始終只檢視了一個例項的鎖情況,而oracle的job執行 在兩個例項上都有可能存在。修改tns地址為第二個例項後,在第二個例項上找到了好幾個全表鎖的程式。

三殺

登陸到第二個例項上,kill掉鎖的程式後1分鐘不到,所有的鎖都降下去了,重啟應用,恢復正常。

總結

事情錯綜,所以總結一下為兩點來將整體內容再簡化一下。

  • 因: 生產業務表在業務繁忙期間執行了全表更新語句,與應用上更新單條記錄的程式形成迴圈鎖、阻塞,導致整體應用和資料庫問題。所以,生產業務表在業務繁忙期間應禁止執行全表更新語句。碰到必須在業務期間全表執行則需採用分批更新和提交,來減小衝突的產生機率,這裡說的全表更新包括更新語句沒有where條件和where條件的結果有大量資料的兩種情況。

  • 果: 找出所有鎖,殺掉所有鎖。需要注意的是:Job會不停產生更新任務。生產環境一般都做了rac,需檢查資料庫的多個例項,都進行kill。

實際上這次事故處理時間有點長,中間停起應用、分析日誌這些都有做,還有遷移介面、排查程式碼這些,處理的內容也相當多。回想起來做的事情就一項是有用的:找到所有鎖,然後kill



作者:georgekaren
連結:
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2310/viewspace-2802320/,如需轉載,請註明出處,否則將追究法律責任。

相關文章