在平时的数据库的使用中,在对表进行插入、修改或删除时经常会遇到sql执行时间过长的阻塞现象,这是多个会话同时对同一张表进行操作,前面的会话没有进行提交或回滚,资源没有释放,后面的会话会一直等待前面会话锁资源的释放,从而出现的阻塞现象,甚至会出现两个事务因争夺锁资源造成的互相等待的死锁现象,接下来我们通过模拟阻塞和死锁来了解一下他们是如何产生和怎么去解决这种现象。       

1 模拟阻塞和死锁

1.1创建两个表并插入数据

create table locktest1 (t1 int);
create table locktest2 (t1 int);
insert into locktest1 values (1);
insert into locktest2 values (2);

java 达梦 pom java 达梦 事物提交延迟_死锁

 

1.2会话1对表locktest1进行修改

对表locktest1中的数据进行update操作

update locktest1 set t1=3 where t1=1;

java 达梦 pom java 达梦 事物提交延迟_dba_02

 

1.3会话2对表locktest2修改

对表locktest2中的数据进行update操作

update locktest1 set t1=4 where t1=2;

java 达梦 pom java 达梦 事物提交延迟_java 达梦 pom_03

1.4会话1对表locktest2修改

update locktest1 set t1=6 where t1=2;

发生阻塞,因为会话2对表的locktest2的修改没有提交或回滚,锁资源没有释放,会话1会一直等待

 

java 达梦 pom java 达梦 事物提交延迟_java 达梦 pom_04

 

1.5会话2对locktest1进行修改

修改后,发生死锁,两个事务已经产生了等待环,都在互相等待对方释放锁资源,产生死锁时达梦会自动进行处理,kill掉会话2对locktest1修改这个事务

 

java 达梦 pom java 达梦 事物提交延迟_java 达梦 pom_05

2分析

当产生锁等待锁等待时,我们可以通过查询系统动态视图来进行综合分析

2.1查询v$trxwait视图

该视图可以显示事务的等待信息,ID为该事务的事务ID,WAIT_FOR_ID为所等待的事务ID,26765为会话1对locktest2的修改,26754为会话2对locktest2的修改

 

java 达梦 pom java 达梦 事物提交延迟_死锁_06

2.1查询v$LOCK视图

该视图可以看事务的锁信息,拿到等待事务的ID后,我们可以查看事务的锁信息,会话2中事务26764对表locktest2进行修改,上了排他锁,同时会话1事务26765对表locktes2进行修改,同时新增了共享锁,因为会话2上了排他锁,没有提交或回滚,锁资源没有释放,造成阻塞

 

java 达梦 pom java 达梦 事物提交延迟_dba_07

 

2.2查询v$sessions视图

 拿到事务ID后,可以通过该视图查询出具体的会话信息,包括具体的sql语句

java 达梦 pom java 达梦 事物提交延迟_回滚_08

3处理阻塞

阻塞和死锁本质上是多个事务同时并发对同一个对象进行访问、修改,先来的事务进行修改后没有即时释放锁资源导致后来的事务一直在等待,甚至在多个会话中两个以上的事务互相等待锁资源的释放导致的死锁现象,这种情况可以手动干预,通过上诉分析方法找出相应的会话和事务,执行提交或回滚造成阻塞的事务,锁资源释放,sql顺利执行,也可以手动结束会话;

通过查询v$trxwait视图,找出阻塞的事务ID,查询v$sessions视图,根据事务ID找出造成阻塞的会话,以本次模拟的阻塞为例,事务26764造成了阻塞,结束该会话;

java 达梦 pom java 达梦 事物提交延迟_死锁_09

 

执行 sp_close_session(1632080168); 手动执行结束会话

事务26765执行成功

java 达梦 pom java 达梦 事物提交延迟_回滚_10