根據開發反饋,最近每天早上7:30應用會報警,應用的日志顯示數據庫連接池滿了,新的連接被拒絕。
首先,我做了ASH報告(報告區間:7:25 ~ 7:35),從ASH的等待事件發現enq: TX - row lock contention居然高達76.54%,如下所示:
Top User Events
Event |
Event Class |
% Event |
Avg Active Sessions |
enq: TX - row lock contention
Application
76.54
0.81
CPU + Wait for CPU
CPU
12.76
0.14
db file sequential read
User I/O
7.40
0.08
enq: TX - row lock contention等待事件是一種行的等待事件,也就是說同一時刻有多個session請求修改同一行。
下一步就是找這個等待事件主要由哪些SQL引起的:
Top SQL with Top Events
SQL ID |
Planhash |
Sampled # of Executions |
% Activity |
Event |
% Event |
Top Row Source |
% RwSrc |
SQL Text |
4rm17788qwxuy
1272661853
54
69.45
enq: TX - row lock contention
69.45
UPDATE
69.45
update shift_case set expertId...
1cqbcdr0ufyk6
1272661853
10
5.20
enq: TX - row lock contention
5.20
UPDATE
5.20
update shift_case set daySecti...
1anu5c146v8d7
1272661853
4
1.89
enq: TX - row lock contention
1.89
UPDATE
1.89
update shift_case set daySecti...
gbw4zk8jv0n0u
2588599834
10
1.57
CPU + Wait for CPU
0.79
TABLE ACCESS - BY GLOBAL INDEX ROWID
0.47
select sc.scId, sc.estId, ct.c...
dvmk92c1umc97
905317021
9
1.42
CPU + Wait for CPU
1.42
CONNECT BY - NO FILTERING WITH START-WITH
0.63
select h.hospitaluuid id, h.pl...
從上表可以得出,SQL_ID=4rm17788qwxuy的SQL語句是罪魁禍首,改SQL語句如下:
4rm17788qwxuy
update shift_case set expertId = :1 , shiftDate = :2 , daySection = :3 , rcLimit = :4 , orderingCount = :5 , shareRccount = :6 , clinicTypeUuid = :7 , fee = :8 , isTimeDivision = :9 , state = :10 , isopen=:11 , stateTime = :12 , updateTime = sysdate where scId =:13
scid是shift_case的主鍵,也就是說同一時刻有非常多的session在請求更新同一行。
好了,既然已經定位到問題就好辦了,馬上把應用開發人員找來一問,真相大白:原來該應用需要從外部系統獲取數據,為了讓內部的數據庫和外部的盡量保持一致,每次查詢外部系統時,會在數據庫裡執行update語句。
解決辦法也簡單:由於每次的Update都會把前一次的update覆蓋(等於前面的update做的都是無用功),所以根本沒必要每次查詢都update,只要最後一次查詢做update就可以了。