死锁定义:
两个事务都在等待对方持有的资源锁,要等待对方释放有的资源锁之后才能继续工作,两者互不想让,坚持到底,都在等待彼此完成才继续工作,就是这样的状态,双方都完成不了,从而陷入死循环。
解决策略:
数据库中的机制是当发生死锁时会牺牲其中的一个进程来让其继续执行下去。
那种情况是应用程序BUG产生的,需要调整程序的逻辑结构,在对多表进行操作时,尽量按照相同的顺序执行,避免同时锁定两个资源,必须同时锁定两个资源的时候,要保证在任何时候都要按照相同顺序来锁定资源。
会话阻塞:
是第一个事务占有资源没有释放,而第二个事务需要获取这个资源,如果第一个事务没有提交或者回滚,第二个事务会一直等待下去,直到第一个事务释放该资源为止。
解决策略:
被阻塞的事务会一直挂起、直到持有锁的事务放弃锁定的资源为止(提交/回滚);
程序应用bug产生,需要调整程序的逻辑结构,尽量形成短事务,快速提交,避免阻塞时间过长,不要将其他无关操作放到容易引起阻塞的模块。
锁的类型:
锁模式指定并发用户如何访问锁定资源。DM数据库使用四种不同的锁模式:共享锁、 排他锁、意向共享锁和意向排他锁。
1、事务锁:
--创建测试表
create table test01(id int primary key, name varchar(20));
--执行查询操作
select * from test01;
--此时查看v$lock该表的锁,可以看到有IS锁。
--获取ID
select o.name, o.id
from sysobjects o
where o.name = 'TEST01';
--查看锁类型
select
t.TRX_ID,
t.LTYPE,
t.LMODE,
t.BLOCKED,
t.TABLE_ID,
t.TID
from v$lock t
where t.table_id = '1037';
打开一个新的会话,再test01中插入一条测试数据(未提交)
insert into TEST01(id, name) values (1, 'baiye');
查看锁类型
2、锁等待:
INSERT 锁等待
当多个事务同时试图向有主键或UNIQUE 约束的表中插入相同的数据时,前一个事务未提交,后面的事务将被阻塞,直到前一个事务提交或回滚。
再开一个会话(会话二),再插入与会话一相同的数据,因为该表有主键,会话一未提交,此时可以看到会话被阻塞
查看v$lock可以看到新增了TID共享锁(S锁),并且该锁blocked=1,该锁被事务48918(会话一)事务阻塞:
提交会话一的数据,再次查询,事务锁释放,会话二报错
UPDATA和DELETE锁等待
当UPDATE和DELETE修改的记录已经被另一个事务修改过(未提交),将会发生阻塞,直到未提交的造成阻塞的事务提交或回滚。
再开一个会话(会话三),更新 id 为 1 的记录
–更新会话数据会话3
update test01 set name = ‘dufu’ where id = ‘1’;
–删除会话数据会话4
delete test01 where id = ‘1’;
select * from SYS."V$TRXWAIT";
处理锁等待
--查看处于等待中的锁,v$lock或者v$trxwait查看阻塞的事务
select
TRX_ID,
LTYPE,
LMODE,
BLOCKED,
TABLE_ID,
TID
from v$lock
where blocked = '1';
通过事务ID(TRX_ID)找到会话ID
使用 sp_close_session 系统过程即可杀死会话,释放阻塞。
也可以使用操作系统命令 kill -9 线程ID 杀死线程,上面查询的 THRD_ID 为线程ID
call sp_close_session(144304536);
再次查询v$lock可以看到会话阻塞的问题解决。
3、死锁
创建第二张表TEST02
create table test02(id int primary key, name varchar(20));
会话一:对 TEST01 插入一条数据(此时 TEST01 表上有了排他锁)。
insert into test01(id, name) values(3, 'Wang Wu');
会话二:对 TEST02 插入和 TEST01 相同数据(此时 TEST02 表上有了排他锁)
insert into test02(id, name) values(3, 'Wang Wu');
在会话一上往 TEST02 表插入相同数据,因为有主键,产生锁等待
insert into test02(id, name) values(3, 'Wang Wu');
在会话二上往 TEST01 表插入相同数据,此时产生死锁,可以看到DM数据库 自动检测到死锁的产生,并报出错误
insert into test01(id, name) values(3, 'Wang Wu');
死锁的本质也是锁等待
DDL锁超时
当我们对某张表执行DDL操作时,若当前表上有排他锁(未提交的DML事务),此时数据库会根据锁的等待时间抛出锁超时的异常。
DM数据库的DDL锁超时时间是由参数 DDL_WAIT_TIME 指定,默认十秒,可根据实际需要修改。
select * from v$dm_ini t where t.PARA_NAME = 'DDL_WAIT_TIME';
--新增会话一,在 TEST01 表中插入数据(未提交),产生一个排他锁:
insert into test01(id, name) values(5, 'Zhao Liu');
--新增会话二,执行DDL语句(对 TEST01 新增字段),此时会话处理等待状态:
alter table test01 add column age varchar(50);
--可以看到事务处于阻塞等待
超时自动报出异常。
达梦社区地址:https://eco.dameng.com
文章
阅读量
获赞
