锁与阻塞
1,定义
阻塞:多个线程之间的相互影响,等待临界资源;
死锁:多个线程之间互相等待,形成等待环;
对于死锁,达梦数据库会自动检测,并选择牺牲掉其中的一个事务,保证其它事务正常运行。
死锁一般是由于应用程序bug导致的,当有修改多表的事务时,应尽量保证每个事务以相同的顺序锁定表。
可以通过V$DEADLOCK_HISTORY查询死锁历史,其中记录了产生死锁后被牺牲掉的事务的事务ID、会话ID、执行的SQL语句以及死锁发生时间(没有记录造成死锁的其它事务)。
对于阻塞,达梦数据库不会自动处理,被阻塞的事务会一直挂起,直到获取到所需的资源。
阻塞一般是由应用程序bug造成的,在应用编写中,应尽量形成短事务,快速提交。
2,什么情况下会形成阻塞?
在达梦数据库中,默认采用读提交的机制,查询永远不会被阻塞。查询一般情况下也不会阻塞增删改操作,SELECT FOR UPDATE的情况除外。
INSERT语句被阻塞的情况:多个事务同时向有主键或唯一约束的表中插入相同的数据;
删、改语句被阻塞的情况:所需要操作的数据被其它事务修改过,且一直没有提交或回滚;
阻塞的排查
当阻塞发生时,我们可以通过 v$lock 视图查到当前数据库中锁的状态
select * from v$lock;
同样我们也可以通过 V$TRXWAIT 视图排查阻塞,
select * from v$trxwait;
接下来,通过 V$SESSIONS 视图查找两个事务对应的会话,可以知道是哪些 SQL 语句产生的阻塞。
select sess_id,sql_text,state,trx_id from v$sessions where trx_id in('号','号');,
3,阻塞的解决方法
根据需求,可以有两种解决方案。
提交或回滚产生阻塞的事务。
关闭产生阻塞的会话
同样,我们也可以使用系统过程 SP_CLOSE_SESSION(SESS_ID)
来关闭对应的会话
此时,锁被释放,delete 操作也可以顺利进行下去。
备注:可以用一条语句查看出被阻塞的操作和事务会话 ID(SESS_ID)
select a.*,b.NAME,c.SESS_ID from v$lock a
left join sysobjects b on b.ID=a.TABLE_ID
left join v$sessions c on a.TRX_ID=c.TRX_ID;
然后直接执行SP_CLOSE_SESSION(SESS_ID)
来关闭对应的会话
详情关注达梦官方https://eco.dameng.com