Chinaunix首页 | 论坛 | 博客
  • 博客访问: 656181
  • 博文数量: 77
  • 博客积分: 6055
  • 博客等级: 准将
  • 技术积分: 617
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-17 02:15
个人简介

一句话太少

文章分类

全部博文(77)

文章存档

2018年(1)

2015年(1)

2014年(1)

2013年(6)

2011年(1)

2010年(1)

2009年(4)

2008年(2)

2007年(21)

2006年(39)

我的朋友

分类: DB2/Informix

2008-01-30 14:06:23

sqlcode -244 死锁问题解决
停掉informix数据库
onmode –ky
启动informix数据库
Oninit
这个问题通常是因为锁表产生的。要么是多个用户同时访问数据库导致该问题,要么是因为某个进程死了以后资源未释放导致的。如果是前一种情况,可以考虑将数据库表的锁级别改为行锁,来减少撞锁的机会;或在应用程序中,用set lock mode wait 3这样的语句,在撞锁后等待若干秒重试。如果是后一种情况,可以在数据库端用onstat -g ses/onstat   -g   sql/onstat   -k等命令找出锁表的进程,用onmode   -z命令结束进程;如果不行,就需要重新启动数据库来释放资源。
 
方法一
Onmode -u 将数据库服务器强行进入单用户模式,来释放被锁的表。生产环境不适合。
方法二
1:$ onstat -k | grep HDR+X
HDR+X 为排他锁
HDR 头
X 互斥
owner
是正持有锁的线程的共享内存地址
2:$ onstat -u |grep c60a363c
c60a363c 为1中查到的owner内容。
sessid
是会话标识符编号
3:$ onstat -g ses sessid
根据sessid得到进程pid
pid
与此会话的前端关联的进程标识
$ onstat -g sql sessid
通过上面命令查看执行的sql语句
4:$ ps -ef |grep pid
由此,我们可得到锁表的进程,可根据实际锁表进程的重要程度的具体情况采取相映处理方法:
对于重要且该进程可以自动重联数据库的进程,可以用onmode  -z sesid 的方法杀掉锁表session,
$ onmode –z sessid
否则也可直接杀掉锁表的进程 kill pid。
$ kill -9 pid
 
将表的页锁改为行锁  
  参考语句为  
  unload   to   optimize.sql   delimiter   ""   select   'alter   table   '||tabname||    
  '   lock   mode(row)'||';'from   systables   where     locklevel="P"   and   tabid   >   99  
  将卸载的optimize.sql稍微删除一下其中出现的字符或乱码,后运行,即可把表的页锁改为行锁
 
onstat -k 输入内容描述:
address
是锁表中锁的地址
如果用户线程正在等待该锁,则锁的地址出现在 onstat -u(用户)输出的 wait 字段中。
wtlist
是正在等待锁的用户线程(如有)列表中的第一项
owner
是正持有锁的线程的共享内存地址
此地址对应于 onstat -u(用户)输出的 address 字段中的地址。
lklist
是刚才列出的所有者所持有锁的链接列表中的下一个锁
类型
使用以下代码指示锁的类型:
HDR

B
字节
S
共享
X
互斥
I
意向
U
更新
IX
意向-互斥
IS
意向-共享
SIX
共享的意向-互斥
tblsnum
是已锁定资源的表空间编号
rowid
是行标识号
行标识提供以下锁信息:
如果行标识等于 0,则该锁为表锁。
如果行标识以 2 个 0 结束,则该锁为页锁。
如果行标识为 6 个数字或更少且不以 0 结束,则该锁很可能是行锁。
如果行标识多于 6 个数字,则该锁很可能是索引键值锁。
key#/bsiz
是索引键号或对 VARCHAR 锁的已锁定字节数
如果该字段包含“K-”,后跟值,则是键锁。值标识哪个索引正在被锁定。例如:K-1 表示对表所定义的第一个索引上的锁。
可用锁的最大数量以 ONCONFIG 文件中的 LOCKS 进行指定。
 
查找锁定的表名称
通过onstat -k 查找的rowid 等于0的表锁信息的 tblsnum 信息查找表名。 
如 tblsnum等于500e19
执行 select * from systables where hex(partnum)='0x00500e19'
查找到当前锁表的表名。
 
 
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 -G

DATABASE 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 对应。

 

如下解释 onstat -x 的输出

address
是事务结构的共享内存地址
flags
位置 1 的标志代码(当前事务状态):
A
用户线程已连接到事务
S
TP/XA 暂挂的事务
C
TP/XA 正在等待回滚
位置 2 的标志代码(事务方式):

T
紧耦合方式(MTS)
L
松耦合方式(缺省方式)
位置 3 的标志代码(事务阶段):

B
开始工作
P
准备好用于提交的分布式查询
X
准备好用于提交的 TP/XA
C
正在提交或已提交
R
正在回滚或已回滚
H
正在尝试回滚或已回滚
位置 5 的标志代码(事务类型):

G
全局事务
C
分布式查询协调者
S
分布式查询从属者
B
分布式查询协调者和从属者
userthread
是拥有事务的线程(rstcb 地址)
locks
是事务持有的锁数
beginlg
是 BEGIN WORK 记录已记录到其中的日志
curlog
是事务正在写入的当前日志
logposit
是日志位置
4 字节日志位置的格式是 0xPPPPPBBB,其中 PPPPP 是日志中的页偏移量,BBB 是页中的字节偏移量。logposit 可以是日志文件中的 0x100000(或 1048576)页的最大数。

isol
是隔离级别。
retrys
是启动分布式查询的恢复线程的尝试次数
coord
是从属者正在执行事务时事务协调者的名称
该字段告诉您哪个数据库服务器正在协调两阶段提交。

onstat -x 输出的最后一行指示 maximum concurrent 是自初始化数据库服务器以来并发事务的最大数。

 

如下解释 onstat -G 的输出

address
是事务控制块的内存中地址
flags
是全局事务的当前状态(使用以下十六进制值组合):
x00000001
用户已连接到事务上
x00000002
打开事务
x00000004
xa_start() 和 xa_end() 之间的事务
x00000008
全局事务
x00000010
标记为仅异常终止的事务
x00000020
TP/XA 准备的事务
x00000040
分布式事务
x00000080
异常终止的事务
x00000100
已提交的事务
x00000200
已尝试完成的事务
x00000400
已写入 BEGIN WORK 日志记录
x00000800
回滚已完成
x00001000
已开始提交已删除表和索引
x00002000
已开始异常终止事务
x00004000
未执行撤销操作
x00008000
全局保存点处于活动状态
x00010000
保存点回滚
x00020000
清除死事务
x00040000
事务用于远程数据库服务器
x00080000
事务条目在使用中
x00100000
事务已执行远程工作
x00200000
保存点已开始
x00400000
分布式事务中的协调者
x00800000
分布式事务中的从属者
x01000000
长事务或暂挂事务没有所有者
x02000000
事务正在恢复中
x04000000
对该事务的重做失败
x08000000
对该事务进行的撤销失败
x10000000
当发生 I/O 故障时事务是活动的
x20000000
事务在恢复过程中执行了某些工作
x40000000
事务包含锁
x80000000
事务执行了 DDR 工作
fID
是事务数据的格式标识
gtl
是全局事务的长度
bql
是事务的字节流长度
data
是事务标识和数据的十六进制转储
摘要定义
active
是活动全局事务的数量
total
是动态分配给数据库服务器的事务的当前数量

 

 

 

 

 

 

 

阅读(10236) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~