DM8锁等待和死锁
Posted yangeoooo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DM8锁等待和死锁相关的知识,希望对你有一定的参考价值。
DM事务锁
创建测试表
create table t_test01(id int primary key, name varchar(20));
select * from t_test01;
select name,id from sysobjects where name='T_TEST01';
LINEID NAME ID
---------- -------- -----------
1 T_TEST01 1486
select trx_id,ltype,lmode,blocked,table_id,tid from v$lock where table_id=1486;
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ------ ----- ----------- ----------- --------------------
1 62313 OBJECT IS 0 1486 62313
新窗口插入数据
SQL> insert into t_test01(id, name) values(1, 'cheng');
affect rows 1
再次查询lock表
select trx_id,ltype,lmode,blocked,table_id,tid from v$lock where table_id=1486;
SQL> /
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ------ ----- ----------- ----------- --------------------
1 62313 OBJECT IS 0 1486 62313
2 62314 OBJECT IS 0 1486 62314
3 62314 OBJECT IX 0 1486 62314
锁等待
场景一:INSERT锁等待
create table t_test01(id int primary key, name varchar(20));
select name,id from sysobjects where name='T_TEST01';
LINEID NAME ID
---------- -------- -----------
1 T_TEST01 1487
开启两个新会话执行,第二个会话会等待
insert into t_test01(id, name) values(1, 'cheng');
查询锁 查询v$lock可以看到该对象新增了TID共享锁(S锁),并且该锁BLOCKED=1,该锁被62323
SQL> select trx_id,ltype,lmode,blocked,table_id,tid from v$lock where table_id=1487;
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ------ ----- ----------- ----------- --------------------
1 62323 OBJECT IS 0 1487 62323
2 62323 OBJECT IX 0 1487 62323
3 62324 OBJECT IX 0 1487 62324
4 62324 TID S 1 1487 62323
提交第一个insert into后,可以看到提交之后相关的事务锁已经释放,并且会话二抛出异常:
1* select trx_id,ltype,lmode,blocked,table_id,tid from v$lock where table_id=1487;
SQL> /
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ------ ----- ----------- ----------- --------------------
1 0 OBJECT IS 0 1487 62323
2 0 OBJECT IX 0 1487 62323
3 62324 OBJECT IX 0 1487 62324
02 锁等待解决方法
但实际业务中,我们可能无法手工提交阻塞的会话,此时可以强制杀死会话:
使用如下语句查询处于等待的锁(或查询v$trxwait可以查看阻塞事务):
SQL> select TRX_ID, LTYPE, LMODE, BLOCKED, TABLE_ID, TID
2 from v$lock where blocked=1;
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ----- ----- ----------- ----------- --------------------
1 62324 TID S 1 1487 62326
SQL> select * from v$trxwait;
LINEID ID WAIT_FOR_ID WAIT_TIME
---------- -------------------- -------------------- -----------
1 62324 62326 74926
如上图,根据阻塞的事务ID=62326找到会话ID,可以看到会话id,sql信息:
select SESS_ID,SQL_TEXT,TRX_ID,THRD_ID from v$sessions where TRX_ID=62326;
LINEID SESS_ID SQL_TEXT TRX_ID THRD_ID
---------- -------------------- -------------------------------------------------- -------------------- -----------
1 140159412672120 insert into t_test01(id, name) values(2, 'cheng'); 62326 43777
根据会话ID,使用sp_close_session系统过程即可杀死会话(也可以使用操作系统命令 kill -9线程ID杀死线程,上图中THRD_ID为线程ID):
SQL> sp_close_session(140159412672120);
DMSQL executed successfully
select trx_id,ltype,lmode,blocked,table_id,tid from v$lock where table_id=1487;
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ------ ----- ----------- ----------- --------------------
1 62324 OBJECT IX 0 1487 62324
2 62324 TID S 0 1487 62326
死锁
死锁与阻塞的不同之处在于死锁包括两个或者多个已阻塞事务,它们之间形成了等待环,每个都等待其他事务释放锁。例如事务1给表T1上了排他锁,第二个事务给表T2上了排他锁,此时事务1请求T2的排他锁,就会处于等待状态,被阻塞。若此时T2再请求表T1的排他锁,则T2也处于阻塞状态。此时这两个事务发生死锁,DM数据库会选择牺牲掉其中一个事务。
测试场景如下:
新增会话一:对T_TEST01插入一条数据(此时T_TEST01表上有了排他锁)。
创建相同的表
create table t_test02(id int primary key, name varchar(20));
会话1
insert into t_test01(id, name) values(3,‘qing’);
会话2
insert into t_test02(id, name) values(3,‘qing’);
会话1
insert into t_test02(id, name) values(3,‘qing’);
会话2
insert into t_test01(id, name) values(3,‘qing’);
[-6403]:Deadlock.
used time: 238.724(ms). Execute id is 0.
死锁的本质也是锁等待,所以解决锁等待的问题,就解决了死锁的问题。
SQL> select * from v$trxwait;
LINEID ID WAIT_FOR_ID WAIT_TIME
---------- -------------------- -------------------- -----------
1 62327 62324 194086
SQL> select SESS_ID,SQL_TEXT,TRX_ID,THRD_ID from v$sessions where TRX_ID=62324;
LINEID SESS_ID SQL_TEXT TRX_ID THRD_ID
---------- -------------------- ------------------------------------------------ -------------------- -----------
1 96965128 insert into t_test01(id, name) values(3,'qing'); 62324 43530
used time: 4.119(ms). Execute id is 900.
sp_close_session(96965128);
DDL锁超时
当我们对某张表执行DDL操作时(比如修改某张表的表结构),若当前表上有排他锁(未提交的DML事务),此时数据库会根据锁的等待时间抛出锁超时的异常。
DM数据库的DDL锁超时时间是由参数DDL_WAIT_TIME指定,默认十秒,可根据实际需要修改。
SQL> select * from v$dm_ini t where t.PARA_NAME = 'DDL_WAIT_TIME';
LINEID PARA_NAME PARA_VALUE MIN_VALUE MAX_VALUE DEFAULT_VALUE MPP_CHK SESS_VALUE FILE_VALUE DESCRIPTION PARA_TYPE
---------- ------------- ---------- --------- --------- ------------- ------- ---------- ---------- ---------------------------------------- ---------
1 DDL_WAIT_TIME 10
锁超时场景测试:
新增会话一,在T_TEST01表中插入数据(未提交),产生一个排他锁:
insert into t_test01(id, name) values(2, ‘qing’);
新增会话二,执行DDL语句(对t_test01新增字段),此时会话处理等待状态:
alter table t_test01 add column info1 varchar(50);
SQL> select trx_id,ltype,lmode,blocked,table_id,tid from v$lock where table_id=1487;
LINEID TRX_ID LTYPE LMODE BLOCKED TABLE_ID TID
---------- -------------------- ------ ----- ----------- ----------- --------------------
1 62327 OBJECT IS 0 1487 62327
2 62327 OBJECT IX 0 1487 62327
3 62334 OBJECT IS 0 1487 62333
4 62334 OBJECT IX 0 1487 62333
5 62334 OBJECT X 1 1487 62334
大概十多秒,会话二抛出锁超时的异常:
锁超时的本质原因是锁等待,解决锁等待的问题,就解决了锁超时的问题。
以上是关于DM8锁等待和死锁的主要内容,如果未能解决你的问题,请参考以下文章