DM数据库对于DDL操作引起的锁的解决方案分为两种方法,方法一:是在业务低峰期延长锁超时时间,以及开启快速加列、修改列、删除列提高DDL操作的成功率;方法二:是在无业务情况下,清理干扰会话,进行DDL操作维护。
会话一:向表TEST插入一条语句,INSERT操作成功,但未提交,此刻模拟业务表上DML操作频繁,这是一个长事务语句
SQL> insert into TEST values(3,'AAA');
会话二:向表TEST添加一个字段,此时会报“[-6407]:Lock timeout”的错误,即锁超时错误,添加字段的擦着不会成功
SQL> alter table TEST add column address varchar(100);
alter table TEST add column address varchar(100);
[-6407]:Lock timeout.
在日常工作中,一般不会允许停业务来进行DDL维护操作,因为停止业务的代价会比较高,对于复杂的系统,停机维护更是充满了不可控的隐患和危险。DM数据库可以采用延长锁超时的时间,以及开启快速加列、修改列、删除列提高DDL操作的成功率。DM数据库的DDL操作的锁超时时间缺省为10秒,手动进行动态调整,延长至60秒,以期尽可能的获取业务表的锁,具体操作如下:
参数名 | 缺省值 | 属性 | 说明 |
---|---|---|---|
DDL_WAIT_TIME | 10 | 动态,会话级 | DDL操作的锁超时时间,以秒为单位。有效值围(0~60) |
除此之外还可配合ALTER_TABLE_OPT参数共同使用,尤其在面对大表的时候,效果会出奇的好。参数ALTER_TABLE_OPT可以对加列、修改列、删除列操作进行优化,如下:
参数名 | 缺省值 | 属性 | 说明 |
---|---|---|---|
ALTER_TABLE_OPT | 0 | 动态,会话级 | 是否对加列、修改列、删除列操作进行优化, 0:全部不优化; 1:全部优化; 2: 打开快速加列,对于删除列和修改列与1等效; 3: 打开快速加列,允许指定快速列默认值,其他功能与2时相同 |
动态参数,可以在数据库中实时设置和实时生效,不需要重启数据库:会话级参数,仅仅在当前会话有效,不会影响到其他会话。延长达梦数据库的DDL操作的锁超时时间至60秒,并开启快速加列、修改列、删除列:
在会话一的窗口内,延长达梦数据库的DDL操作的锁超时时间至60秒,再次回到会话二,争取在锁超时的60秒时间内获取到业务表的锁,就可以进行快速DDL维护操作:
会话1:
SQL> SP_SET_PARA_VALUE (1, 'DDL_WAIT_TIME', 60);
DMSQL executed successfully
used time: 8.970(ms). Execute id is 4101.
SQL> SP_SET_PARA_VALUE (1, 'ALTER_TABLE_OPT', 2);
DMSQL executed successfully
used time: 8.316(ms). Execute id is 4102.
会话2:
SQL> alter table TEST add column address varchar(100);
executed successfully
used time: 00:00:04.420. Execute id is 4103.
对于业务侧已确认某时间段无业务访问,可以直接进行DDL操作,但有时依旧报锁等待超时的错误,对此可以使用上述的方式提高我们的操作效率,同时对干扰我们维护的会话进行清理。
我们直接从v$sessions动态视图中可找到会话中关于该表所涉及到的会话,并手动关闭会话,可借助存储语句完成:
SQL> SET SERVEROUT ON # 在块中有打印信息时,默认不会打印,需要手动开启
SQL> declare
session_id bigint;
begin
select sess_id into session_id from v$sessions where sess_id<>sessid and UCASE(sql_text) like '%TEST%';
print session_id;
sp_close_session(session_id);
end
/
达梦数据库中,DML操作是常见的会导致锁等待的语句,DDL操作频繁虽然低,操作不当也会导致锁等待。运维一旦发现锁等待问题,需要配合业务侧及时处理掉,以免锁等待累积造成更严重的现网故障。
模拟达梦数据库DML操作可能会出现的行锁等待,同时打开两个会话窗口,就是在未执行SQL前打开两个会话窗口。
1、会话一:更新表TEST中id=2的(id字段为主键字段)数据,更新成功,但不要提交:
SQL> update TEST set name='BBB' where id=2;
2、会话二:继续更新表TEST中id=2的这行数据,就会出现未更新成功,处于等待状态:
SQL> update TEST set name='CCC' where id=2;
此时会话二处于挂起状态,因为会话二在等待会话一持有的资源,仅当会话一提交或回滚后才能执行成功。已经模拟出锁等待问题,这里需要处理一下锁等待:
1、首先查看被挂起的事务,即找到被挂起事务ID(TRX_ID)
SQL> SELECT VTW.ID AS TRX_ID, VS.SESS_ID ,VS.SQL_TEXT FROM V$TRXWAIT VTW LEFT JOIN
V$TRX VT ON (VTW.ID=VT.ID) LEFT JOIN V$SESSIONS VS ON (VT.SESS_ID=VS.SESS_ID);
LINEID TRX_ID SESS_ID SQL_TEXT
------ ------ -------------- ---------------------
1 6158 139808835965528 update TEST set name='CCC' where id=2;
2、通过挂起事务ID(TRX_ID)找到等待的事务(WAIT_FOR_ID)
SQL> SELECT WAIT_FOR_ID,WAIT_TIME FROM V$TRXWAIT WHERE ID=6158;
LINEID WAIT_FOR_ID WAIT_TIME
---------- -------------------- -----------
1 6157 108572
2、通过等待事务ID(WAIT_FOR_ID)定位到正在执行的语句
SQL> SELECT VT.ID AS TRX_ID,VS.SESS_ID,VS.SQL_TEXT ,VS.APPNAME,VS.CLNT_IP FROM
V$TRX VT LEFT JOIN V$SESSIONS VS ON (VT.SESS_ID=VS.SESS_ID) WHERE VT.ID = 6157;
LINEID TRX_ID SESS_ID SQL_TEXT
-------- -------- ----------------- -------------------------------------
1 6157 139809037292120 update TEST set name='CCC' where id=2;
这种对于引起锁等待的语句,优先kill掉引起锁等待的语句,保障系统稳定运行。后续再对抓取到的语句进行分析和定位。
1、建议先系统自带的函数kill掉引起锁等待的语句:
SQL> SP_CLOSE_SESSION(139809037292120);
2、再查看会话二,就发现update操作已经执行成功:
SQL> update TEST set name='CCC' where id=2;
在DM数据库中,INSERT、UPDATE、DELETE更新操作是最常见的会产生阻塞和死锁的语句。INSERT发生阻塞的唯一情况是, 当多个事务同时试图向有主键或UNIQUE约束的表中插入相同的数据时,其中的一个事务将被阻塞,直到另外一个事务提交或回滚。一个事务提交时,另一个事务将收到唯一性冲突的错误;一个事务回滚时,被阻塞的事务可以继续执行下去。而当UPDATE和DELETE修改的记录,已经被另外的事务修改过,将会发生阻塞的情况,直到另一个事务提交或回滚。
文章
阅读量
获赞