达梦数据库支持多用户并发访问、修改数据。在实际工作中,有可能出现多个事务同时访问、修改相同数据的情况,当一个事务正在占用某个资源的锁,此时另一个事务正在请求这个资源上与第一个锁相冲突的锁的类型时,就会发生阻塞。此时,被阻塞的事务将一直挂起,直到持有锁的事务放弃锁定的资源为止。下面将给大家介绍如何对应的动态性能视图查看阻塞以及如何解决阻塞。
(演示环境)数据库版本:DM Database Server x64 V8 (Build 2020.01.15) ENT
具体操作步骤:
1.创建测试表
create table T1(“ID” int,“NAME” varchar(50));
2.表中插入数据
begin
for i in 1…100
loop
insert into t1 values
(1, ‘dameng’||i
);
end loop;
commit;
end;
3.在T1表上面生成TID锁,执行update操作并且不提交,具体操作如下:
4.开启新会话,在新会话下执行select操作
可以看到,由于MVCC的多版本机制,写不会阻塞读,所以select操作可以正常进行。但是前面的事务没有提交,所以查出来的结果还是旧版本的数值,也就是update之前的值。
5.在新会话下执行DML操作
此时,由于delete操作需要加上与之前update操作相同类型的锁,所以阻塞发生,事务被挂起。
6.阻塞的排查
当阻塞发生的时候,我们可以通过v$lock视图查到当前数据库中锁的状态
select * from v$lock;
7.同样我们也可以通过V$TRXWAIT视图查找谁阻塞谁
得出同样的结论,ID为21517的事务正在等待21505的事务,等待的时间是334565毫秒。
8.通过V$SESSIONS视图查找两个事务对应的会话
select sess_id,sql_text,state,trx_id from v$sessions;
select sql_text from v$sessions join v$trxwait on trx_id = wait_for_id;
select sql_text from v$sessions where trx_id in (select wait_for_id from v$trxwait);
可以得到两个事务对应的会话ID和当前执行SQL语句,可以知道是哪些SQL语句产生的阻塞。
阻塞的两种解决方法:
方法一:提交或回滚产生阻塞的事务
根据上文,我们可知产生阻塞事务的id号140633402546904。此时,我们只需要在该会话下提交(commit)或回滚(rollback)事务,锁自然会被释放,阻塞解决。
方法二:关闭产生阻塞的会话
同样,我们也可以使用系统过程SP_CLOSE_SESSION(SESS_ID)来关闭对应的会话,具体的使用方法如下:
此时,锁被释放,delete操作也可以顺利的进行下去