内容


Informix 长事务 (Long Transaction) 详解

Comments

什么是“长事务”?

要理解什么是“长事务”,还要从“事务”本身及数据库的逻辑日志工作原理谈起。所谓“事务”(transaction),是一个完整的不可分割的数据处理单元。该单元中所有的数据处理操作要么全部处理成功,要么因其中任意一个操作的失败而完全回滚至整个事务处理前状态。为了保证事务的完整性,Informix 数据库通过逻辑日志 (logical log) 来记录所有的事务操作及其处理的数据。逻辑日志的作用之一在于对数据所发生的变化进行记录以满足可能的回滚需要。

Informix 数据库服务器把逻辑日志分成多个相互分离的磁盘空间,每个磁盘空间称为一个逻辑日志文件。由于逻辑日志文件的大小和个数由参数指定,整个逻辑日志的空间是相对固定的,并不能无限制的增长。所以对于逻辑日志文件的使用是循环进行的。Informix 数据库服务器按数字顺序依次填充空闲的(即状态为 free 或 available)的逻辑日志文件。当第一个逻辑日志文件变满时,接着开始填充下一个逻辑日志文件,直到填充完最后一个逻辑日志文件。这时,数据库服务器回到第一个逻辑日志文件,试图将其内容释放,以循环使用 ( 如图 1)。

图 1. 循环使用的逻辑日志
图 1. 循环使用的逻辑日志

释放已经使用过的逻辑日志,需要具备很多条件。其中之一就是该日志不能包含仍然活动的 ( 即还没有提交 ) 的事务。 因为活动的事务随时存在需要回滚的可能性,如果在事务还没有提交时,包含该事务记录的日志由于被释放重用,原来的事务操作记录被覆盖,当事务由于各种原因需要回滚时,回滚所需的记录就会缺失,从而导致无法保证事务的原子性和完整性。

那么,当数据库服务器需要循环使用某个逻辑日志文件,而该文件又包含有还没有提交的事务时,数据库系统就将被挂起 (hang), 处于一种停滞状态,任何对数据库的更新操作都无法继续,从而影响系统的正常处理工作 ( 如图 2)。

图 2. 长事务导致系统挂起
图 2. 长事务导致系统挂起
图 2. 长事务导致系统挂起

为了防止这种现象的发生,我们把占用整个逻辑日志空间在一定比例以上的事务,就叫做“长事务”。“长事务”意味着可能由于跨越过多的日志文件,导致需要循环使用的日志文件不能及时释放。从而造成数据库系统挂起无法正常工作的可能性。

与长事务相关的数据库参数

那么究竟多长的事务就是“长事务”呢?事实上,“长事务”由一系列数据库参数决定。

LOGFILES

该参数指定系统初始化或重启动时创建的逻辑日志文件的个数。之后系统管理员还可以继续追加逻辑日志文件数。Informix 数据库要求逻辑日志文件最少有 3 个,最多可以追加到 32,767 个或直至逻辑日志所在空间 (dbspace) 被占满。

LOGSIZE

该参数指定创建的逻辑日志文件的缺省大小。当系统管理员手工追加日志文件时,可以重新指定日志文件大小。

所以逻辑日志文件的个数和其大小决定了系统可用逻辑日志空间的总和。

Long-Transaction High-Watermark (LTXHWM)

长事务深水线比例是指整个逻辑日志空间的一个百分比值。当一个事务占用整个逻辑日志空间的百分比超过这个值时,该事务就成为长事务。数据库系统系统就会强制对该事务进行回滚(rollback ), 以防止该事务继续填充日志,最终导致日志需要循环重用时无法释放而造成系统挂起。

例如,数据库服务器有 10 个逻辑日志文件,如果 LTXHWM 设置为 80 。一个事务(transaction )从日志文件 1 (log1 )开始填充,随着该事务的更新 (update) ,当其操作填充到第 8 个日志文件满时,该事务就到达了长事务深水线比例(LTXHWM ),为了防止系统挂起,数据库服务器将回滚该事务。

Exclusive Access, Long-Transaction High-Watermark (LTXEHWM)

当一个事务到达长事务深水线比例(LTXHWM )后,数据库服务器会回滚该事务。事务回滚本身也会产生日志,仍然要继续填充日志空间。同时,由于并发事务的存在,其他事务也在不断填充日志空间。所以如果在该事务完全回滚之前,日志空间被填满,仍然会造成系统的挂起。为了尽量避免这种情况的发生,我们用独享的长事务深水线来限制长事物回滚时其他事务对日志空间的使用。

独享的长事务深水线也是整个逻辑日志空间的一个百分比值。当正在回滚的长事务占用日志空间的百分比到达这个值时,系统会急剧降低对日志文件的填充速度。此时,数据库系统几乎给予正在回滚的长事务以独占使用剩余日志空间的权利,以最大限度地保障长事务回滚能够在日志空间添满前能够顺利完成,从而使日志释放重用得以实现。

例如,数据库服务器有 10 个逻辑日志文件,如果 LTXHWM 设置为 80, LTXEHWM 设置为 90 。一个事务(transaction )从日志文件 1 (log1 )开始填充,随着该事务的更新 (update) ,当其操作填充到第 8 个日志文件满时,该事务就到达了长事务深水线比例(LTXHWM ),为了防止系统挂起,数据库服务器开始回滚该事务,此时日志内容由于该事务回滚和其他事务继续增长,当其操作填充到第 9 个日志文件满时,如果该事务还未回滚完成,则到达独享的长事务深水线比例(LTXEHWM ),这时候数据库系统会暂停其他事务的操作(除 commit 操作外),留下剩余的日志空间,让该事务回滚,以防止日志空间在回滚结束前被占满。( 如图 3)

图 3. 长事务深水线比例(LTXHWM)与独享的长事务深水线比例(LTXEHWM)示意
图 3. 长事务深水线比例(LTXHWM)与独享的长事务深水线比例(LTXEHWM)示意
图 3. 长事务深水线比例(LTXHWM)与独享的长事务深水线比例(LTXEHWM)示意

DYNAMIC_LOGS

从 Informix Dynamic Server (IDS)版本 9.30 开始,用户可以通过对数据库参数中的 DYNAMIC_LOGS 参数进行设置以实现系统逻辑日志的自动分配。该参数允许用户在服务器工作状态动态添加新的日志并且立即生效,从而动态增加整个逻辑日志空间的大小,消除或减小长事务处理引起挂机的可能性。

DYNAMIC_LOGS 参数有三个值分别为 0,1,2:

  • 缺省为 2( 系统自动分配日志 )。假如当前使用的日志为 n,系统自动为 Transation 检查 log n+1 的状态,如果返回的结果为真 ( 即 Log n+1 无法被释放而重用 ),系统将在 n 和 n+1 之间加入新的日志并一直增加到满足当前 Transation 完成且立即生效。新增加的日志缺省建立到逻辑日志最后被添加的 dbspace 中,或根据系统规则建立到指定的 dbspace 中。新增日志的大小将取已有最大日志和最小日志的均值。或根据请求空间的大小进行相应的调整,日志最小为 200K。
    图 4. 逻辑日志的动态分配示意
    图 4. 逻辑日志的动态分配示意
    图 4. 逻辑日志的动态分配示意
  • 当 DYNAMIC_LOGS 参数设置为 1 时,系统也自动为 Transation 检查 logn+1 的状态,如果返回的结果为真 ( 即 Log n+1 无法被释放而重用 ),系统将等待系统管理员手工在当前日志后添加日志,系统管理员可以在任何时间使用 ISA 或 onparams 多种方式为系统添加日志。
  • 如果 DYNAMIC_LOGS 参数为 0,系统将不会自动添加日志也不会出现等待状况。

什么情况下会出现长事务

从以上数据库参数可以看出,长事务与整个日志空间大小有关,与长事务深水线比例有关。直接来看,在整个逻辑日志空间相对固定的前提下,当一个事务越大(包含的操作越多),其需要填充的逻辑日志空间就会越大。如果该事务需要记录的日志占用整个逻辑日志的百分比超过长事务深水线比例(LTHWM),该事务就成为长事务。

那么,如果我们能够预计最复杂的事务需要填充日志空间的大小,如果我们分配给系统足够大的日志空间(系统整个日志空间 *LTHWM/100 > 最复杂的事务需要填充的日志空间),是不是就完全能够杜绝长事务的发生呢?另外,一个非常小的事务(其实际填充的日志空间远远小于系统整个日志空间)是不是就一定不会成为长事务呢?

答案并非如此。

事实上,事务之所以成为长事务,其所占日志空间定义为该事务从第一条日志记录到最终 commit 或者 rollback 记录之间的所有日志空间。当这个空间占用整个逻辑日志空间的百分比超过长事务深水线比例时,该事务就成为长事务了。

首先,事务包含的操作的多少只是决定该事务是否将成为长事务的因素之一。还有其它一些因素会影响事务占用逻辑日志空间的大小。例如,一条 Alter table 虽然仅仅是一个操作,但语句将会为每一次往新修改了的表中的插入操作生成一条逻辑日志记录。数据行的数量与表的大小都将会影响生成的逻辑日志记录的数目与大小。操作的数据行数越多,生成的逻辑日志记录越多,所占用的逻辑日志空间既然越大。

其次,在另外一些情况下,虽然事物的操作和数据行大小并不大,但由于系统并发的存在,事务的持续时间也是一个不能为用户所控制的主要的变化量。在事务持续时间中,该事务所占日志空间中可能包含了许多其他并发事务的日志记录。因此,系统的并发性越大,事务的操作时间越长,事务占用 ( 跨越 ) 的逻辑日志空间就越大。一个应用,也许并不需要过多的逻辑日志记录空间,但如果用户允许事务在很长时间内保持打开,这时就可能造成长事务事件。

发生长事务事件的结果及影响

当一个事务所跨逻辑日志空间的百分比超过长事务深水线比例 (LTXHWM) 时,系统会将该事务标记为长事务,并开始回滚 (rollback) 该事务。如果此时还没有达到独享的长事务深水线比例 (LTXEHWM) ,则系统在回滚该事务的同时允许其他并发事务的继续操作。当该事务日志占用超过独享的长事务深水线比例 (LTXEHWM) 时,系统会暂停其他并发事务的进行,优先进行该事务的回滚操作,直到事务回滚完成。如果在该事务回滚完成之前,系统逻辑日志空间已被全部占满,则数据库系统会挂起,无法为客户端继续提供正常服务。

所以,只要配置足够的逻辑日志空间和较低的长事务深水线比例 (LTXHWM)、独享的长事务深水线比例 (LTXEHWM),就有可能保证长事务的顺利回滚。但是,长事务的出现,会影响业务的正常操作,导致该事务无法执行成功。而且,长事务独享日志回滚期间,也会影响整个系统的并发效率。

然而,最糟糕的情况莫过于出现长事务回滚完成之前,系统逻辑日志空间已被全部占满,从而带来致命的系统挂起,给系统运营带来损失。

如何监控长事务

当数据库系统发生长事务事件时,可以在所有 onstat 命令的输出头上看到。“onstat –”命令(不带有任何选项)只输出头部信息,对于观察系统的状态非常有用。其输出模式如下:

 Version--Mode (Type)--(Checkpnt)--Up Uptime--Sh_mem Kbytes

当系统出现长事务时,可能的输出为:

 Dynamic Server Version 11.50.UC1--On-Line(Long TX)--Up 15:11:41--9216 Kbytes

当数据库系统由于各种原因被阻止时,在以上 onstat 输出下方还会有如下显示:

 Blocked: reason

其中,“reason”可能的跟长事务相关的值见表 1:

表 1. 系统受阻的原因 ( 跟长事务相关的原因 )
原因代码值 原因解释
LONGTX Long transaction
LBU Logs full high-watermark

另外,“onstat -x”命令还可以看到回滚的事务 ( 如图 5 所示 )。 在输出的 flag 列中,第三个位置上的标记如果为“R”,说明该事务正在回滚或已回滚。也可以用“onstat -x|grep R” 命令将其从众多的事务列表中选出。当然回滚的事务不一定都是长事务。

图 5. 回滚的事务
图 5. 回滚的事务
图 5. 回滚的事务

有时侯,事务回滚需要很长的时间,如果该事务处于独享的长事务深水线区域,很多并发的操作无法执行,用户常常误以为系统发生了崩溃。这时,可以用“onstat -lr” 命令,通过观察逻辑日志的写 ( 占用 ) 情况来判断系统是否还处于正常的活动工作状态。

图 6. 判断系统是否还处于正常的活动工作状态
图 6. 判断系统是否还处于正常的活动工作状态
图 6. 判断系统是否还处于正常的活动工作状态

如何避免长事务以及如何处理长事物带来的系统挂起

保证在系统需要时,有足够的逻辑日志空间使用,尽量避免长事务带来的困扰,维护系统正常运转,这是数据库管理员的职责。那么,该如何避免长事务以及如何处理长事物带来的系统挂起呢?

首先,最基本的一点是最大限度地保证逻辑日志可用空间,满足事务的需要。对于逻辑日志空间的配置应该考虑到应用中最大的事务的操作的多少,以及各操作可能涉及的数据的多少,从而保证该事务所需要的实际物理日志空间得以满足。不考虑并发因素,如果参数的设置满足如下公式,则不会出现长事务现象。

系统整个逻辑日志空间 * 长事务深水线比例(LTXHWM)/100 > 任意事务对于日志空间的实际物理占用

但实际情况远远没有这么简单。由于系统并发的不可控性,以及事务执行当时,数据量的不可预知性,我们似乎没有办法预知应该为逻辑日志分配多少空间。而且,有时侯,容易成为长事务的 transaction 可能执行频率相当低(如批量装载事务,可能一个月,甚至一年才执行一次),如果为其计算出来的所需日志空间非常大,那么预留这样的日志空间对于系统的日常运行来说也是相当浪费。

从 Informix Dynamic Server (IDS)版本 9.30 开始,用户可以通过对数据库参数中的 DYNAMIC_LOGS 参数进行设置以实现系统逻辑日志的动态自动按需分配。有了这个参数以后,长事务深水线比例 (LTXHWM) 不再象以前(版本 9.30 以前)那么关键地去影响长事务的发生以及造成系统挂起了。因为数据库系统的日志空间可以动态增长了,直到数据库所在系统物理空间被占满。

动态追加逻辑日志可以有效防止长事务的发生及由此而引起的系统挂起。当当前正在被填充的日志文件的下一个日志文件包含有活动(尚未提交)的事务时,系统将允许动态追加逻辑日志文件。

所以合理设置 DYNAMIC_LOGS 参数,可以有效减小长事务发生的概率。无论是将其设置为 1( 手工动态追加日志 ), 还是 2( 自动动态追加日志 ),都能让 Informix 数据库服务器动态即时追加逻辑日志。随着逻辑日志空间的增长,长事务深水线也会增长,事务成为长事务的机率就会降低。即使由于事物日志记录空间的增长速度超过系统追加日志空间的速度,从而使事务到达长事务深水线比例 (LTXHWM),在长事务回滚期间(该长事务和其他并发事务继续产生日志记录),数据库系统仍然可以动态分配追加日志空间以满足长事务回滚的需要,直到其回滚完成。

例如, 数据库服务器配置了 10 个逻辑日志文件,长事务深水线比例 (LTXHWM) 设置为 98。假设一个事务从日志文件 1 开始,其操作填充了日志 1 到 9,在开始使用日志文件 10 时,这时候该事务占用日志空间比例为 9/10,还没有到达 0.98,也就是说还没有成为长事务。这时候数据库服务器开始动态追加日志文件 11。只要该事务没有成功完成,这个过程会重复进行直到当数据库服务器追加到第 50 个日志文件时,此时,该事务使用到了第 49 个日志文件,其占用日志空间比例为 49/50,刚好到达 0.98,也就是说该事务成为长事务,开始进行回滚。

但这样的情形不会太多,可能还没有等到系统追加到第 50 个逻辑日志,该事务已经成功提交 (commit) 了。

保障足够的逻辑日志空间以及支持动态日志空间增长是避免长事务的重要手段。同时,降低长事务深水线比例 (LTXHWM) 和独享的长事务深水线比例 (LTXEHWM) ,虽然不能减小长事务发生的概率,却能够有效减小长事务发生后导致系统挂起的可能性。如果可用的逻辑日志空间有限,预计发生长事务的可能性较大时建议将长事务深水线比例 (LTXHWM) 设置为 50, 独享的长事务深水线比例 (LTXEHWM) 设置为 60,以保证系统的安全。

但有时, 我们也可能需要根据具体情况对长事务深水线比例 (LTXHWM) 和独享的长事务深水线比例 (LTXEHWM) 进行调整。如,为了保证长事务回滚期间系统的并发处理能力,我们可以加大独享的长事务深水线比例 (LTXEHWM);为了顺利运行一个计划的未知大小的事务(如批量加载),我们可以适当加大长事务深水线比例 (LTXHWM) 以保证该事务不会成为长事务而遭到回滚。如果系统有充分足够的空间,在 DYNAMIC_LOGS 参数设置为 1 或 2 的前提下,想让一个未知大小的事务顺利执行而不受长事务问题的困扰,甚至可以考虑将长事务深水线比例 (LTXEHWM) 设置为 100,从而迫使数据库服务器在需要的时候持续追加逻辑日志,直到该事务执行成功 (commit)。同样,为了保证长事务回滚期间系统的并发处理不受影响,可以将独享的长事务深水线比例 (LTXEHWM) 设置为 100,这样一来,数据库服务器可以不断追加足够多的逻辑日志,以保证长事务回滚结束,防止系统因缺乏空闲逻辑日志而挂起。

需要注意的是,即使数据库系统的日志空间可以动态增长,一旦受到系统物理空间的限制,长事务深水线比例 (LTXHWM) 和独享的长事务深水线比例 (LTXEHWM) 参数仍然用来防止逻辑日志被事务占满而无法释放重用的情况发生。只是这种情况发生的概率应该更小。而一旦发生,预示着应用系统的严重隐患。所以加强应用系统对于处理长事务的考虑,通过减小事务的长度,更频繁地提交事务等手段,都能很好地控制长事务的发生。

一般来说,我们对参数的建议如下 :

  1. 如果系统有大量的物理空间,DYNAMIC_LOGS 参数可以设置为 1 或 2, 长事务深水线比例 (LTXHWM) 和独享的长事务深水线比例 (LTXEHWM) 分别设置为 80 和 90。
  2. 如果因为分配给数据库系统的逻辑日志空间有限,DYNAMIC_LOGS 参数设置为 0,长事务深水线比例 (LTXHWM) 和独享的长事务深水线比例 (LTXEHWM) 分别设置为 50 和 60。

这里只是对一般系统的一个通常的建议,如果因为某种需要,降低长事务深水线比例 (LTXHWM),就意味着增加了长事务出现的可能性,当然还可以通过分配更多的日志空间来做补偿。

如果预防不力,在实际生产系统中发生由于长事务而导致的系统挂起,又该如何处理呢?

发生系统挂起事件,从数据库日志(online.log )中可以看到相应的事件信息。为了解决这个问题,通常有如下做法:

  1. 如果想让该长事务继续进行,需要:
    1. 增加一个 dbspace 或者在原有 dbspace 上增加 chunk, 以增加日志可用空间
    2. 恢复该事务处理
  2. 如果无法增加更多的空间给数据库服务器,则需要终止该事务
    1. 发出“onmode -z ”命令终止相应长事务
    2. 关闭 (shutdown) 数据库服务器,进行重启 (oninit)
    3. 当数据库服务器重启进入快速恢复(fast-recovery)状态时,该事务被回滚。然后执行如下步骤:增加更多的磁盘空间,直到该事务回滚成功完成。
  3. 如果由于其他原因,系统无法从挂起状态下恢复,唯一的途径就是从备份中进行恢复:
    1. 执行一个基于时间点的恢复,将系统恢复至该长事务开始前的时间点
    2. 执行一个完全的 0 级恢复,释放掉所有逻辑日志空间

结束语

长事务是数据库系统为了保护自身的良好运行,防止由于事务占用过多的日志空间而采取的一种控制手段。在系统运行过程中,我们应该合理设置与长事务相关的数据库参数,有效避免长事务的发生,同时积极监控系统状态,在发生长事务的时候,根据具体需求和情况给予合理处理,从而保证系统的正常运行。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=465278
ArticleTitle=Informix 长事务 (Long Transaction) 详解
publish-date=01282010