Informix锁表产生的原因,要么是多个用户同时访问数据库导致该问题,要么是因为某个进程死了以后资源未释放导致的。如果是前一种情况,可以考虑将 数据库表的锁级别改为行锁,来减少撞锁的机会;或在应用程序中,用set lock mode wait 3这样的语句,在撞锁后等待若干秒重试。如果是后一种情况,可以在数据库端用onstat -g ses/onstat -g sql/onstat -k等命令找出锁表的进程,用onmode -z命令结束进程;如果不行,就需要重新启动数据库来释放资源。
1:$ onstat -k | grep HDR+X
获得sessid,其中HDR+X 为排他锁,HDR 头,X 互斥 ,sessid 是会话标识符编号。
2:$ onstat -g ses sessid
根据sessid得到进程pid,其中pid 是与此会话的前端关联的进程标识。
(可通过$ onstat -g sql sessid 命令查看执行的sql语句)
3:$ ps -ef |grep pid
由此,我们可得到锁表的进程,可根据实际锁表进程的重要程度的具体情况采取相映处理方法:
对于重要且该进程可以自动重联数据库的进程,可以用onmode -z sesid 的方法杀掉锁表session:
$ onmode –z sessid
否则也可直接杀掉锁表的进程 kill pid:
$ kill -9 pid
至此,死锁即被清除掉。
查找锁定的表名称
通过onstat -k 查找的rowid 等于0的表锁信息的 tblsnum 信息查找表名。
如 tblsnum等于500e19
执行 select * from systables where hex(partnum)=’0×00500e19′
查找到当前锁表的表名。
Informix -244 错误 :
Could not do a physical-order read to fetch next row.
具体错误解释:
#finderr -244
原因:
a.锁表
b.记录太多
c.页损坏
d.某个进程死了以后资源未释放导致
在数据库端用 onstat –g ses/onstat –g sql /
Onstat –k 等找出锁表进程,用onmode –z结束该进程,
不行,重启数据库释放。
锁方式:
行方式(row),页方式(默认page),表方式(table)。
解决:
1.降低锁级别
2.减少加锁事务的时间跨度
3.设置等待解琐时间
相关命令:
)检查索引及页损坏情况
#oncheck –cID database_name:table_name
) 查看锁级别
#oncheck –pt database_name:table_name
)设置锁级别(行方式)
#alter table table_name lock mode(row)
)设置隔离级别
#set isolation to dirty read
)设置等待解锁时间(不宜过大)
#set lock mode to wait second(秒)
不等待
#set lock mode to not wait
还可以这样解决:如果是日志型数据库,在执行的时候,可以先锁定begin work;lock table tab_name in exclusive mode;要执行的sql语句;commit work;如果是非日志的数据lock table table_name in exclusive mode;要执行的sql语句;unlock table tab_name;
中间件全局事务锁问题中间件与informix连接时会出现onstat -k 中 owner 内容为0的现象。这是应该查看全局事务onstat -x 和onstat -GDATABASE sysmaster;select hex(tx_addr) trans_addr,hex(tx_lklist) lock_addr from systrans
where hex(tx_addr) like '%c00000006e329778%';需要说明的是,c000000007674c58是使用onstat -x 或 onstat -G得到的全局事务的地址。上面SQL语句提供出该全局事务对应的锁地址,这时如果得到的锁地址与锁表的锁地址相同的话,
你就必需从应用端(通常是三层结构的中间件)发命令让该全局事务回滚或提交,否则该锁会被一直持有,直到你执行oninit。
onstat -k 的owner 列中的地址与onstat -x 中的userthread 对应。