注册
达梦数据库模拟阻塞死锁及解锁
培训园地/ 文章详情 /

达梦数据库模拟阻塞死锁及解锁

三米 2023/07/03 3277 2 0

模拟阻塞如下:
CREATE TABLE TBL_TEST(ID INT PRIMARY KEY, NAME VARCHAR(50));
INSERT INTO TBL_TEST VALUES(1, '中文');

在第一个会话窗口创建测试表,更新一条数据,不提交事务
1.jpg

在第二个会话窗口执行同一条插入语句,此时会卡住,发生阻塞
2.jpg

原因分析:第一个窗口里,插入的数据由于没有 commit 提交,事务没有结束,此时因为存在主键约束,第二个窗口查不到对应的数据,同样也无法插入,此时发生阻塞。

解决阻塞办法:

通过 V$TRXWAIT 视图查看进程,找到ID,ID对应着V$SESSIONS视图的SESS_ID:
此处的48198即为被阻塞的事务ID
select * from V$TRXWAIT ; WAIT_FOR_ID ---等待事务的ID
3.jpg

再通过V$SESSIONS视图,查找对应的ID号确定阻塞语句
SELECT SESS_ID,SQL_TEXT,TRX_ID from V$SESSIONS;
4.jpg

调用 SP_CLOSE_SESSION(SESS_ID);系统函数来关闭会话。
5.jpg

如何避免阻塞(有两种方法):
1.在第一个窗口使用 commit 指令提交:
2.在第一个窗口使用 rollback,第二个窗口可正常插入。

死锁

1,第一个窗口执行
update TBL_TEST set "NAME" = '测试' where id =1;
6.jpg
2,第二个窗口执行
update TBL_TEST set "NAME" = 'ceshi' where id =2;
7.jpg
3,第一个窗口执行,此时会发生阻塞
update TBL_TEST set "NAME" = 'cece' where id =2;
8.jpg
4,第二个窗口执行
update TBL_TEST set "NAME" = 'cece' where id =1;
9.jpg

死锁与阻塞的不同之处在于死锁包括两个或者多个已阻塞事务,它们之间形成了等待环,每个都等待其他事务释放锁。例如事务1给表T1上了排他锁,第二个事务给表T2上了排他锁,此时事务1请求T2的排他锁,就会处于等待状态,被阻塞。若此时T2再请求表T1的排他锁,则T2也处于阻塞状态。此时这两个事务发生死锁,DM数据库会选择牺牲掉其中一个事务。

死锁的本质也是锁等待,所以解决锁等待的问题,就解决了死锁的问题。

解锁如下:
select * from V$TRXWAIT ;
SELECT SESS_ID,SQL_TEXT,TRX_ID,THRD_ID from V$SESSIONS where TRX_ID=57223;
SP_CLOSE_SESSION(SESS_ID); 关闭会话
10.jpg

当dm.ini中的参数ENABLE_MONITOR=1时,使用死锁历史动态试图V$DEADLOCK_HISTORY,可以查询到发生过的死锁信息。
Select * from V$DEADLOCK_HISTORY;

11.jpg

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服