一个长事务引起的血案——Informix 长事务回滚失败引起的阻塞故障处理

   四大名捕是我看过题材最多的电影。武侠,悬疑,惊悚,科幻,爱情。励志,动作,推理,喜剧,冒险。只有你想不到,没有你看不到。就好像把所有山珍海味倒马桶里给大家吃一样。
  如果仅仅是只要也就算了,整部影片没有一点逻辑所在,没有逻辑的组合,没有逻辑的相爱,没有逻辑案件,没有逻辑竞争。没有逻辑的结尾。他在烂片里是很成功的。

Informix 11.5数据库,双机hdr热备。这是背景。

这两天出了个事情:由于一个大事务引起了逻辑日志耗尽,导致数据库状态进入出现了叫做“长事务阻塞Blocked:LONGTX”的状态中,停止服务。本文分析其原理与解决办法。

1   长事务阻塞的原理

当事务开始时,数据会在在所在的逻辑日志文件中记录一个检查点Check
Point,事务运行时,这个检查点及之后的逻辑日志都处于未提交状态,要被保留一直到事务提交或是回滚,这些逻辑日志才能标志为使用过,并能再次被循环利用。

如果事务中的操作很多,事务就会跨多个逻辑日志文件。当事务使用的逻辑日志文件超过一定量后,就判断为“长事务”。因为事务回滚也是需要使用逻辑日志的,所以,当数据库发现长事务使用的逻辑日志数目到达“回滚折返点”时,这就意味着如果继续执行事务,剩下的事务可能不足以保证此长事务回滚,数据库就会中断事务执行,并立即回滚。

但因为回滚过程也是需要使用逻辑日志的,在回滚中一但出现逻辑日志不够用的情况,回滚操作用完了剩余的逻辑日志文件,却还没有回滚完成,数据库就会发生“长事务阻塞”。这种情况会出现在一个长事务回退时,另一个事务又快速消耗剩余日志等情况下。

注意这里的逻辑日志不够用指得不是有没有ontape
–c备份过,而是指因为事务的起始检查点在第N个逻辑日志文件里,而现在已经执行到了第N-1个逻辑日志文件里(informix的逻辑文件是循环的,执行到N-1号就意味着追了尾了),也就是所有的逻辑日志文件都处于未提交状态,但是当前事务还是不够用,这种情况下,就算所有的日志文件都已经被ontape
–c备份过了,也不能被再次利用,因为事务的回滚或是提交还没有完成。

请参考 

2   现象与检查

在这时候,如果你检查数据库的状态,会是如下的样子:

infodb% onstat -
IBM Informix Dynamic Server Version 11.50.FC6     -- On-Line (Prim LONGTX) -- Up 35 days 16:41:40 -- 3920896 Kbytes
Blocked:LONGTX

 

可以执行onstat –x来检查事务情况

infodb% onstat -x

IBM Informix Dynamic Server Version 9.40.FC7     -- On-Line (LONGTX) -- Up 35 days 16:41:56 -- 3920896 Kbytes
Blocked:LONGTX
Transactions
address          flags userthread       locks  beginlg curlog  logposit   isol    retrys coord
1c8b2b298        A---- 1c8ae9850        0      0       0       0x0        COMMIT  0     
1c8b2b508        A---- 1c8aea078        0      0       0       0x0        COMMIT  0     
1cd4d7918        A-B-- 1d44fdcb0        2      119408  119507  0x39722c   DIRTY   0     
1cd4d8068        A---- 1cd576e38        1      0       0       0x0        COMMIT  0     
1cd4d82d8        A---- 1cd577660        1      0       0       0x0        DIRTY   0     

 

注意其中的flags为 “A-B—“ 的事务,B状态表示begined,
说明这个事务还在执行中。注意他的beginlg也就是开始时的逻辑日志文件号为119408,而当前的日志已经到了119507,
两者相差减加1就是100,正是这个informix系统里所设置的日志数量(您的系统可能不同),这说明这个事务把所有的逻辑日志文件全部用完了。

如果执行onstat –l检查逻辑日志文件的使用情况,会看到下面的情况:

2a273c368  27       U-B----  119506   7:250053            12500    12500   100.00
2a273c3d0  28       U---C--  119507   7:262553            12500        0    18.50
2a273c438  29       U-B---L 119408   7:275053            12500     2313   100.00
2a273c4a0  30       U-B----  119409   7:287553            12500    12500   100.00
2a273c508  31       U-B----  119410   7:300053            12500    12500   100.00

 

 

所有的日志已经备份过了,但是由于L标示在119408,说明有事务从这里开始,现在还没有提交或是回退,而当前已经到了119507,所有的逻辑文件用了一圈,已经没有日志可以用了,但当时工作还没有做完。

 

查看log文件(是指那个文本文件),会看到如下的内容:

17:59:34  Aborting Long Transaction: tx: 0x1cd4d7918   username: informix uid: 300
17:59:35  Long Transaction 0x1cd4d7918   Aborted. Rollback Duration: 0 Seconds
… 这里是一大段检查点与逻辑日志用完和备份的信息,直到……
18:03:22  ALERT: The oldest logical log (119408) contains records from
          an open transaction (0x1cd4d7918).  Logical logging will
          remain blocked until a log file is added.  Add the
          log file with the onparams -a command, using the -i
          (insert) option, as in:

          onparams -a -d <dbspace> -s <size> -i

          Then complete the transaction as soon as possible.

 

这里的意思是说,最老的那个逻辑日志文件包括了一个开放着的事务,逻辑日志会阻塞,直到增加一个新的逻辑日志文件。要增加逻辑日志文件,可以用onparams
–a,并使用-i选项,就像下面的命令,这样就能尽快结束这个事务了。

 

onparams –a –d <dbspace> -s <size> -i

 

这个命令的意思是:用dbspace的空间来增加一个逻辑日志文件,大小为size,
并插入在当前日志的后面。

发表评论

电子邮件地址不会被公开。 必填项已用*标注