? ? 從15年四月份開始,某項目組線上服務老反饋有服務掛掉問題,具體表現為服務不可用,但java進程是存活狀態。經排查,發現是大量寫操作線程在等待數據庫返回。當時第一反映是數據表死鎖了,導致線程等待,因此先入為主地做了判斷,也如是交待項目組開發人員。現在看來,技術人員最忌諱的是自以為是。
? ? 自此以為問題結束了,但4月份后,陸續會聽到類似的問題再出現,由于該項目我不直接處理,后續問題也未反饋到我手上,也不以為意,直到最近一個月,線上服務一再出問題,幾經輾轉還是回到我手上了。
? ? 問題惡心的地方在于不能穩定復現,折騰了一兩天,查了業務代碼,實在是太亂,加之現象十分詭異,通過oracle的視圖定位,竟然是select語句造成了行鎖,導致其他的update語句等待。查詢語句如下:
select ls.osuser os_user_name,ls.username?user_name,ls.type?lock_type,
o.object_name?object,decode(ls.lmode,1,null,2,'Row?Share',3,'Row?Exclusive',4,'Share',5,'Share?Row?Exclusive',6,'Exclusive',null)?lock_mode,o.owner,
ls.sid,ls.serial#?serial_num,ls.id1,ls.id2,ls.lockwait?from?sys.dba_objects?o,
(select?s.osuser,s.username,l.type,s.lockwait,l.lmode,s.sid,s.serial#,l.id1,l.id2??from?v$session?s,v$lock?l?where?s.sid=l.sid)?ls
where?o.object_id=ls.id1?and?o.owner<>'SYS'?order?by?o.owner,o.object_name
這個現象讓我十分崩潰,已經超出了我的認知能力,無法想象為何一個select語句能導致行鎖。沉下心來查oracle各種相關視圖,終于發現一點端倪:block session的狀態是inactive,這意味著block session已經執行完畢,只是未提交。這點通過java的線程也能得到佐證。為了進一步驗證,在oracle sqlplus開兩個客戶端,模擬相關操作,終于復現了一樣的場景。
? ? 接下來的事情變得簡單些,排查java代碼中哪些事務未提交。最終發現,開發人員在使用nutz事務時,采用了非官方的寫法,而使用方式又有問題,導致事務未提交。