knightnibo
作者knightnibo·2017-03-02 11:15
数据库管理员·亚博科技

Informix锁表问题处理

字数 1130阅读 1743评论 0赞 2

锁表问题是很常见的情况,在测试环境下锁的数量较少,所以可以清晰的看出问题所在并处理。而在生产环境下则会出现成百上千的锁,甚至存在一些由于游标操作,导致无法看到实际锁的情况,具体大概可以分为以下几种情况

1.测试环境中的锁表问题

这种情况很简单,参考最简单的锁表处理方法即可

onstat -k|grep X

IBM Informix Dynamic Server Version 9.40.FC6     -- On-Line -- Up 5 days 08:30:34 -- 3638480 Kbytes
Locks
address          wtlist           owner            lklist           type     tblsnum  rowid    key#/bsiz
700000000d471b8  0                7000000c848dbb0  0                HDR+S    100002   205         0
700000000d4dd10  0                7000000c04c07f8  0                    S    100002   305         0

找到对应owner列
然后onstat -u|grep owner
然后找到对应session id跟pid
然后断开还是杀进程自己选

2.实际生产环境中的锁表问题

这种情况本质上与第一种没有区别,但是则复杂一些,应用操作时一般是需要访问多个表的数据进行,所以当第一个应用呈现等待状况的时候,后续应用会相继进入等待,并将锁问题由源头表扩展至众多表上,呈现海量锁和众多应用超时的状况,看起来就会发现似乎一堆表被锁住,不知何处才是源头
但我们整理一下思路就会发现,这种情况像是一条锁链,环环相扣,除了第一个owner的session成功的执行了操作且没有释放外,其他人都同时处在owner和waiter列表中,这样我们就可以通过找出不在waiter列表中的owner,来发现其源头
当然实际生产环境中,则可能并不止一条锁链的存在,所以其实按照该方法我们会找到的也许不止一个源头,但正常情况下,锁是不会持续太久的,所以持续存在的那个则更大概率是我们要找的源头,找出SQL后结合应用逻辑也能够帮助更加准确的进行判断。

下面这个是我比较常用的SHELL来找出持有顶端锁的session,当存在多条链的时候,则会通过表名参数找出需要的session。

\\#!/bin/sh
if [ $# -eq 0 ];then
dbaccess sysmaster</dev/null|grep -v ^$
select a.dbsname database,a.tabname,rowidlk lk_rid,type lk_type,a.owner lk_sid,b.username,b.uid,b.pid,b.hostname,b.tty,c.sqs_statement locker_sql from sysmaster:syslocks a,sysmaster:syssessions b,sysmaster:syssqlstat c 
where a.waiter is null 
and a.owner=b.sid 
and b.sid=c.sqs_sessionid 
and a.dbsname not like 'sys%'
EOF
else
tab=`echo $1|tr [A-Z] [a-z]`
dbaccess sysmaster</dev/null|grep -v ^$
select a.dbsname database,a.tabname,rowidlk lk_rid,type lk_type,a.owner lk_sid,b.username,b.uid,b.pid,b.hostname,b.tty,c.sqs_statement locker_sql from sysmaster:syslocks a,sysmaster:syssessions b,sysmaster:syssqlstat c 
where a.waiter is null 
and a.owner=b.sid 
and b.sid=c.sqs_sessionid 
and a.dbsname not like 'sys%' 
and a.tabname='${tab}' 
EOF
fi

3.特殊锁表问题

出现这种情况有可能是由于有其他的用户在表上使用了游标进行数据读取。由于游标并不在具体的数据记录上放置任何锁,所以我们就可能能够将该表以排他的方式锁住,但是它却会防止其他用户对表的信息进行修改。

方法1:重启数据库最彻底
方法2:断掉应用

如何定位:传统方式是查找sysmaster:syslocks根据owner来定位,或者onstat -g sql|grep databasename
这2个办法都比较宽泛,精确定位比较困难,一个比较好的方法,则是通过打开的对象来进行过滤,尽管其上并不包含实际的锁,但打开的操作仍然会记录下相应的rstcb,所以处理方法如下:

1.找出对象PARTNUM

非分片表

Select hex(partnum) from systables where tabname = "customer"

分片表

Select st.tabname, dbinfo("dbspace", sf.partn), hex(sf.partn) from systables st, sysfragments sf, where st.tabid = sf.tabid and sf.fragtype = "T"and st.tabname = "customer". 

2.找出相应sid

onstat -g opn | grep -i 
onstat -u | grep 

此处注意:取的rstcb值是不含0x

3.获取sid/pid并处理

[informix] onstat -g ses 
[informix]ps -ef |grep 
kill 

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

2

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广