首页 > 数据库 > 国内数据库 > 达梦数据库阻塞/死锁模拟
在项目实际运行中,可能由于程序逻辑冲突或者人为操作 导致多个会话同时对一张表的同一条数据进行修改( 即第一个连接占有资源没有释放,而第二个连接需要获取这个资源),如果第一个连接没有提交或者回滚,第二个连接会一直等待下去,这就产生了阻塞。对于阻塞,数据库无法处理,所以对数据库操作要及时地提交或者回滚;
另一种情况:第一个连接占有资源没有释放,准备获取第二个连接所占用的资源,而第二个连接占有资源没有释放,
准备获取第一个连接所占用的资源。 这种互相占有对方需要获取的资源的现象叫做死锁。
对于死锁,数据库处理方法:牺牲一个连接,保证另外一个连接成功执行。
通过本地模拟阻塞和死锁场景,查询动态视图,能够快速定位阻塞问题。
create table t1_deadlock ( a int );
create table t2_deadlock ( a int );
insert into t1_deadlock values ( 1 );
insert into t2_deadlock values ( 2 );
commit ;
会话1执行:修改t1表,不提交

会话2执行,修改t2表,不提交

回到会话1,修改t2表,不提交,
此时产生阻塞

来到会话2,修改t1表:
此时产生死锁

注意:达梦在出现死锁后,会自动kill掉死锁的会话(这里是会话2),然后会话1仍处于阻塞状态,需要手动提交或回滚。
此时即产生了阻塞,查询 v$trx可以看到相关信息:
select status,ID,sess_id from v$trx where status = 'LOCK WAIT';

将 sess_id 放到会话视图中查,可以找被阻塞的SQL:

同时,查询v$lock可以看到与锁有关的信息:
select o.name,l.* from v$lock l,sysobjects o where l.table_id=o.id and blocked=1;

其中 TRX_ID,TID 都对应的是v$sessions中的TRX_ID:

下面是排查阻塞常用的SQL语句:
--查询阻塞源头
select sf_get_session_sql(sess_id)as 阻塞源SQL,
datediff(ss,last_recv_time,sysdate) as "阻塞持续时长(秒)",
TRX_ID,*
from v$sessions where trx_id in (select wait_for_id from v$trxwait where wait_for_id not in (select id from v$trxwait));
--查询所有被阻塞的语句
select a.id as trx_id,a.sess_id,a.status 事务状态,b.sql_text,a.waiting 事务等待的锁,
b.CLNT_IP 客户端IP,b.state 会话状态
from v$trx a
left join v$sessions b on a.sess_id = b.sess_id
where a.status = 'LOCK WAIT' ;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69998466/viewspace-2772070/ ,如需转载,请注明出处,否则将追究法律责任。