1、定義
阻塞:多個線程之間的相互影響,等待臨界資源;
死鎖:多個線程之間互相等待,形成等待環;
對於死鎖,達夢數據庫會自動檢測,並選擇犧牲掉其中的一個事務,保證其它事務正常運行。
select * from V$DEADLOCK_HISTORY;--查詢死鎖歷史
記錄了產生死鎖后被犧牲掉的事務的事務ID、會話ID、執行的SQL語句以及死鎖發生時間(沒有記錄造成死鎖的其它事務)。
對於阻塞,達夢數據庫不會自動處理,被阻塞的事務會一直掛起。應盡量形成短事務,快速提交。
2、 什么情況下會形成阻塞?
在達夢數據庫中,查詢永遠不會被阻塞,SELECT FOR UPDATE的情況除外。
INSERT語句被阻塞的情況:多個事務同時向有主鍵或唯一約束的表中插入相同的數據;
刪、改語句被阻塞的情況:所需要操作的數據被其它事務修改過,且一直沒有提交或回滾
3、 阻塞的排查
1)環境創建
drop table test;
create table test(id int,name varchar);
insert into test values(1,'test');
commit;
select * from test;
2)執行修改
update test set name='test222' where id=1;
3)執行查詢
select * from test where id=1;
4)切換會話查詢
select * from test where id=1;
由於之前的修改事務沒有提交,所以新會話查出來的結果還是舊的值。
5)在新會話執行刪除操作
delete from test where id=1;
此時,發生阻塞,因為 delete 操作需要加鎖,當前事務被掛起。
6)在舊會話中查詢阻塞的事務
select * from v$trxwait;
事務7400被阻塞了,阻塞他的事務為7401,阻塞了249734毫秒。
之所以不在執行delete的會話中查,是因為那個會話卡主了,什么都做不了。
7) 通過 V$SESSIONS 視圖查找兩個事務對應的會話
查哪些 SQL 語句產生的阻塞
select sess_id,sql_text,state,trx_id from v$sessions where trx_id in('7400','7401');
4、阻塞的解決方法
根據需求,可以有兩種解決方案。
4.1 提交或回滾產生阻塞的事務。
rollback;
commit;
4.2 關閉產生阻塞的會話
使用系統過程 SP_CLOSE_SESSION(SESS_ID)來關閉對應的會話
SP_CLOSE_SESSION(1981579576);
注意:sess_id指的是v$sessions中的sess_id。
更多資訊請上達夢技術社區了解: https://eco.dameng.com