分类: DB2/Informix
2007-12-06 10:38:33
本文将详细讨论如何配置和管理逻辑日志。本文还将通过一个实际生活中的例子演示如何估计和预测逻辑日志的使用情况。
逻辑日志(logical log)是数据库管理的一个重要方面。如果没有得到适当的管理,逻辑日志将给数据库管理员带来许多头痛的事。最常见的一些问题是:
本文将详细讨论如何配置和管理逻辑日志。本文还将通过一个实际生活中的例子演示如何估计和预测逻辑日志的使用情况。
|
逻辑日志实际上是一组文件,这些文件保存了自上次 0 级备份以来数据库事务和数据库服务器变更的历史记录。逻辑日志文件不是普通的操作系统文件。它们是由 Informix Dynamic Server 在第一次初始化期间自动创建的,由 Informix Dynamic Server onparams实用程序管理。逻辑日志文件是循环的。换句话说,在它们被填满之后,又可以一次接一次地重复使用。但是,对于重用有一定的条件:
在配置逻辑日志时,我们需要注意以下问题:
此外,下面有一些性能方面的考虑:
要了解关于如何有效地配置逻辑日志的细节,请参考 IBM Informix Dynamic Server Administrator's Guide, Version 9.4(在本文中引作 Administrator's Guide)的第 13 章。
逻辑日志由 onparams实用程序管理,该实用程序允许添加、删除(drop)和移动逻辑日志。如前所述,在第一次初始化期间,Informix Dynamic Server 将自动创建一些逻辑日志。它所创建的逻辑日志的数量是由配置文件中的 LOGFILES 参数规定的。此后,使用 onparams实用程序添加、删除或者移动逻辑日志。 Onparams有以下选项:
onparams -a -d |
要使用 onparams 实用程序,有两个先决条件:
请参考 Administrator's Guide以了解关于如何使用该实用程序的细节。
如何阅读和解释逻辑日志的内容,逻辑日志记录带有什么样的有用信息呢?通常的操作系统编辑器,例如 vi不能直接读逻辑日志;只能使用 onlog实用程序来读逻辑日志。该实用程序提供了以下功能:
onlog显示逻辑日志记录时有两个选项,即 onlog -l和 onlog -n。例如,假设我们刚完成了一个数据库事务,该事务包含对一个表的一次更新。现在执行 onlog -l,看看逻辑日志如何记录这个事务:
addr len type xid id link 18 48 BEGIN 20 155 0 07/01/2003 15:34:08 737 eric 00000030 009b0001 00000000 00009af8 ...0.... ........ 00000014 00000000 0427bcdf 00000000 ........ .'...... 00000000 3f01f040 0000006e 000002e1 ....?..@ ...n.... 48 60 HUPDAT 20 0 18 3000c1 1707 0 108 108 1 0000003c 00000049 00008010 00006d91 ...<...I ......m. 00000014 00000018 0427bcdf 00000000 ........ .'...... 003000c1 00001707 00000000 006c006c .0...... .....l.l 00010003 00020100 00000000 ........ .... 84 48 COMMIT 20 0 48 07/01/2003 15:34:08 00000030 00000002 00000010 00006d91 ...0.... ......m. 00000014 00000048 0427bcdf 00000000 .......H .'...... 3f01f040 00001707 00000000 3f01f040 ?..@.... ....?..@ |
输出显示,该事务生成了三条逻辑日志记录,每条记录包含两部分:记录头和 ASII dump。ASII dump 是数据更改的 ASII 码,在这里更新语句是在数据库恢复中使用的。头部是最有趣的地方。它包含很多字段,将提供关于事务的一些有用信息。接下来的表解释了头部的每个字段:
头部字段 | 描述 | 格式 |
addr | 日志位置 | 十六进制 |
len | 以字节计的记录长度 | 十进制 |
type | 记录类型名 | ASII |
xid | 事务号 | 十进制 |
id | 逻辑日志号 | 十进制 |
link | 到事务中前一记录的链接 | 十进制 |
此外,该输出还记录了事务的时间:该事务始于 07/01/2003 15:34:08,在 07/01/2003 15:34:08 时完成。第一条记录标志事务的开始(开始工作),第三条记录标志事务的结束(提交工作)。第二条记录表明该事务只包含一个数据库操作,也就是更新。字段 len表明记录所占的逻辑日志空间。在这里,逻辑日志使用了 156 (所有三条记录的总和,48 + 60 + 48)字节来记录该事务。在估计逻辑日志的使用情况时,这个数字非常有用。在本文的后面还将有与此相关的更多讨论。
现在执行 onlog -n,看看输出有什么不同。既然这个选项是用于显示某特定逻辑日志中的逻辑日志记录的,因而就需要一个逻辑日志 id。知道了所有逻辑日志记录都在逻辑日志号 155 中,我们就可以执行 onlog -n 155,以下是输出:
addr len type xid id link 18 48 BEGIN 20 155 0 07/01/2003 15:34:08 737 eric 48 60 HUPDAT 20 0 18 3000c1 1707 0 108 108 1 84 48 COMMIT 20 0 48 07/01/2003 15:34:08 |
这里的输出非常类似于 onlong -l的输出,惟一不同之处是这里省去了逻辑日志记录的 ASII dump 部分。 Onlog -n选项只报告逻辑日志记录的头部。
让我们看一个更复杂的例子。再次假设我们刚刚完成了一个事务,但是这次该事务比起前面的事务要复杂得多。这次该事务包括一组数据库操作。
它创建一个表,插入一些行,更新行号,删除一行,然后删除这个表。用于记录该事务的逻辑日志是 234。通过使用 onlog -n 234,我们得到以下输出:
addr len type xid id link 2ea81fc 36 CKPOINT 1 0 2ea8018 0 2ea9018 48 BEGIN 38 234 0 07/04/2003 11:28:11 1035 eric 2ea9048 40 UNIQID 38 0 2ea9018 20005c 129 2ea9070 380 BLDCL 38 0 2ea9048 2000d0 8 8 4 0 fan 2ea91ec 44 CHALLOC 38 0 2ea9070 00002:0000032326 8 2ea9218 48 PTEXTEND 38 0 2ea91ec 2000d0 7 00002:0000032326 2ea9248 140 HINSERT 38 0 2ea9218 20005c a0e 90 2ea92d4 88 ADDITEM 38 0 2ea9248 20005c a0e 7 1 36 2ea932c 56 ADDITEM 38 0 2ea92d4 20005c a0e 2 2 4 2ea9364 72 HINSERT 38 0 2ea932c 20005d 1328 24 2ea93ac 60 ADDITEM 38 0 2ea9364 20005d 1328 16 1 6 2ea93e8 56 ADDITEM 38 0 2ea93ac 20005d 1328 17 -32766 4 2ea9420 128 HINSERT 38 0 2ea93e8 20005f 909 77 2ea94a0 120 ADDITEM 38 0 2ea9420 20005f 909 10 1 68 2ea9518 88 ADDITEM 38 0 2ea94a0 20005f 909 7 2 36 2ea9570 52 HINSERT 38 0 2ea9518 2000d0 101 4 2ea95a4 52 HINSERT 38 0 2ea9570 2000d0 102 4 2ea95d8 56 HUPDAT 38 0 2ea95a4 2000d0 101 0 4 4 1 2ea9610 52 HDELETE 38 0 2ea95d8 2000d0 102 4 2ea9644 140 HDELETE 38 0 2ea9610 20005c a0e 90 2ea96d0 88 DELITEM 38 0 2ea9644 20005c a0e 7 1 36 2ea9728 56 DELITEM 38 0 2ea96d0 20005c a0e 2 2 4 2ea9760 72 HDELETE 38 0 2ea9728 20005d 1328 24 2ea97a8 60 DELITEM 38 0 2ea9760 20005d 1328 16 1 6 2ea97e4 56 DELITEM 38 0 2ea97a8 20005d 1328 17 2 4 2eaa038 128 HDELETE 38 0 2ea97e4 20005f 909 77 2eaa0b8 120 DELITEM 38 0 2eaa038 20005f 909 10 1 68 2eaa130 88 DELITEM 38 0 2eaa0b8 20005f 909 7 2 36 2eaa188 36 PERASE 38 0 2eaa130 2000d0 2eaa1ac 48 BEGCOM 38 0 2eaa188 2eaa1dc 44 CHFREE 38 0 2eaa1ac 00002:0000032326 8 2eaa208 36 ERASE 38 0 2eaa1dc 2000d0 2eaa22c 48 COMMIT 38 0 2eaa208 07/04/2003 11:28:11 2eab018 484 DPT 1 234 0 37 2eab1fc 36 CKPOINT 1 0 2eab018 0 |
这个事务比第一个事务大得多,它生成了更多的逻辑日志记录。换句话说,比起先前的那个事务,这里逻辑日志占用了更多的空间来记录该事务。这个事务所使用的总空间可以通过求输出中所有 len字段的和算出。在这个例子中,逻辑日志使用了 3556字节的空间来记录这个事务!要获得对以上输出的每个记录类型的详细解释,请参考 Informix Dynamic Server Administrator's Reference。
|
配置了逻辑日志之后,应不断监控逻辑日志的使用情况,以确保有足够的逻辑日志,这样 Informix Dynamic Server 就可以避免前面讨论过的长事务的情况。要监控逻辑日志的使用,需使用 onstat 实用程序。命令 onstat -l 将显示当前逻辑日志的使用情况。以下是 onstat -l 的示例输出:
Informix Dynamic Server Version 9.40.FC1 -- On-Line -- Up 1 days 19:37:46 -- 1818624 Kbytes Physical Logging Buffer bufused bufsize numpages numwrits pages/io P-2 0 16 178155 11983 14.87 phybegin physize phypos phyused %used 1:263 8750 6413 0 0.00 Logical Logging Buffer bufused bufsize numrecs numpages numwrits recs/pages pages/io L-2 0 16 1695756 319940 227242 5.3 1.4 Subsystem numrecs Log Space used OLDRSAM 1695756 241316428 address number flags uniqid begin size used %used 16f4a7e90 4 U-B---- 244 7:53 15000 15000 100.00 16f4a7ee8 5 U---C-L 245 7:15053 15000 7558 50.39 16f4a7f40 6 U-B---- 166 7:30053 15000 15000 100.00 16f4a7f98 7 U-B---- 167 7:45053 15000 15000 100.00 16f181218 8 U-B---- 168 7:60053 15000 15000 100.00 16f181270 9 U-B---- 169 7:75053 15000 15000 100.00 16f1812c8 10 U-B---- 170 7:90053 15000 15000 100.00 7 active, 7 total |
看看该输出的底端部分。 Number字段表明逻辑日志号。该号码可能不是连续的,因为 DBA 可能要根据系统需要插入和删除逻辑日志。例如,上面的输出表明,由于某种原因,前三个逻辑日志(号码 1 到 3)已经被删除。 Flags字段表明逻辑日志的状态。U 代表使用过的逻辑日志,B 代表备份过,C 代表当前正在使用,L 代表有最后检查点记录的逻辑日志。上面的输出表明,逻辑日志 5 被使用过,但当前仍在使用,而且它有最后检查点记录。 Uniqid字段是惟一的日志 id。由于逻辑日志是循环的,当逻辑日志被重用时,该号码就会改变。Size 字段表明按页计算逻辑日志有多大(一页大约 2 k 字节)。Used 字段表明事务记录所使用的空间,这也是按页计算的。 %used字段表明逻辑日志的使用百分率。要获得该输出中所有字段的详细描述,请参考 Administrator's Reference的第 13 章。
为了监控当前事务的逻辑日志使用情况,下面有一个小小的 shell 脚本。它基本上是使用 onstat -l命令,但是它还计算通过该命令收集到的统计数字,然后输出该事务所使用的逻辑日志空间,这里是以百分比表示的。
#!/bin/sh $INFORMIXDIR/bin/onstat -l | awk -F" " ' BEGIN { t_flag=0 } { if ($1 == "address") { t_flag=1 } if ( t_flag == 1 ) { if ( $1 == "address") { t_logsize=0 t_logused=0 } else { if ( substr($3,3,1) != "B" ) { t_logused=t_logused+$7 } t_logsize=t_logsize+$6 } } } END { t_logperct=t_logused/t_logsize*100 printf("Logical log space used %-d%\\n",t_logperct) }' |
该脚本在帮助识别当前事务消耗了多少逻辑日志空间时很有帮助。但是有没有更具前瞻性的方法呢?如果将要执行的事务是已知的,那么可不可以预先计算出逻辑日志空间呢?可不可以预测事务能否成功?如果答案是肯定的,那么就可以前瞻性地采取某些行动,例如增加逻辑日志空间或者将事务劈成更小的块以避免长事务。
|
估计逻辑日志的使用情况并非易事,这牵涉到大量的详细分析、测试和计算。下面是一个很好的实际生活中的例子。
我们的客户在运行名为 Move BSC 的程序时,会碰到有关长事务的问题。BSC 是无线电通讯(telecommunication)中的一个网络元素。当 BSC 从一个地方移动到另一个地方时,程序就会执行大量的存储过程,每个存储过程又会执行大量的数据库操作,例如对不同的数据库表进行插入、删除和更新。由于数据库使用了事务日志记录,所有这些操作都被记录在逻辑日志中。用户一次移动过多的 BSC,使用了系统上所有可用的逻辑日志,Informix Dynamic Server 达到了长事务,这些情况都很少发生。因而,整个事务最终会回滚。这导致客户受阻,因为回滚会占用很长的时间,而且会冻结 Informix Dynamic Server 引擎。因此客户请求我们为他们提供一个数学公式,以便估计在开始移动 BSC 之前逻辑日志的使用情况以及一次可以移动的 BSC 的最大数量。
由于逻辑日志的使用与事务紧密相关,我们首先必须识别在 Move BSC 程序中涉及到多少事务。假设一个存储过程的每次执行就是一个事务,因为存储过程中的所有数据库操作都是一起执行的。下面的表列出了 Move BSC 程序中使用或者调用的所有存储过程,以及存储过程的执行次数:
存储过程名 | 执行次数 |
bsc_I | 2 |
bsc_UA | 2 |
cage_I | 4 |
cage_UA | 4 |
slot_I | 64 |
gp_func_I | 12 |
bsc_xcdr_assoc_I | 1 |
te_I | 52 |
te_timeslot_I | 637 |
gp_func_xcdr_I | 6 |
nail_I (xcdr) | 2 |
bsc_D | 2 |
cage_D | 4 |
slot_D | 64 |
gp_func_D | 12 |
bsc_xcdr_assoc_D | 1 |
te_D | 52 |
te_timeslot_D | 637 |
gp_func_xcdr_D | 6 |
nail_D | 3 |
总计 | 1567 |
现在有了以上表的帮助,我们就可以进一步识别出每个事务中涉及到什么样的数据库操作,以及有多少这样的操作。经过仔细研究和分析之后,我们产生了一个表格,这个表格列出了在每个存储过程或者事务中涉及到的所有数据库操作。这份列表相当长,下面只是对该列表的一个摘要,它列出了所有数据库表和在 bsc_D 存储过程中涉及到的相应的操作:
存储过程名 | 表名 | 操作 | 操作次数 |
BSC_D | Neline | Update | 200 |
? | Pvc | Delete | 600 |
? | Tdm | Delete | 100 |
? | BSC | Delete | 100 |
? | Ne | Delete | 100 |
? | Workspace_oplog | Insert | 400 |
? | Workspace_paramlog | Insert | 300 |
然后我们必须为每个存储过程估计逻辑日志的使用情况。这牵涉到大量的测试和计算。我们需要进行大量的测试,以便获得针对在 Move BSC 中涉及到的每个表的每个数据库操作的逻辑日志使用情况的统计数字。接下来,我们要使用通过测试收集到的统计数字,为 Move BSC 程序中的每个存储过程计算逻辑日志的使用情况。在所有数据库操作当中,插入操作要使用大部分的逻辑日志。因此我们决定使用插入作为我们进行估计的基准。首先,识别在存储过程中涉及到的一系列的表,然后将一些行或记录插入到每个表中。接着我们使用 onlog 实用程序来查看由于插入操作而生成的逻辑日志记录有多少,并求每条逻辑日志记录长度的总和。例如,为了为 NE 表估计逻辑日志的使用,在测试数据库时我们插入一行到 NE 表中,然后使用 -n 155,其中 155 是日志 id,这样我们得到以下输出:
addr len type xid id link 18 48 BEGIN 20 155 0 07/01/2003 15:34:08 737 omcadmin 2ea9248 140 HINSERT 38 0 2ea9218 20005c a0e 90 2ea92d4 88 ADDITEM 38 0 2ea9248 20005c a0e 7 1 36 2ea932c 56 ADDITEM 38 0 2ea92d4 20005c a0e 2 2 4 84 48 COMMIT 20 0 48 07/01/2003 15:34:08 |
上面的输出表明,将一条记录插入到 NE 表中将生成三条逻辑日志记录,该数据库操作所使用的总逻辑日志空间是 284 字节,这也是三条记录长度的总和(140 + 88 + 56)。此外,还有 96 字节的事务开销,也就是 BEGIN 和 COMMIT 记录的总和。事务开销是恒定的,每个数据库事务都要加上这一项。在这里,也就是对于存储过程的每次执行都要考虑这一项。结果,我们得出下面的表,这个表列出了将一条记录插入到 Move BSC 程序中涉及的每个表中的逻辑日志的使用:
表名 | 按字节计算的逻辑日志的使用 |
bsc | 448 |
bsccage | 300 |
bsccard | 324 |
bsclink | 378 |
bscnail | 424 |
ccb | 308 |
cpxcdr | 304 |
ds | 248 |
gpfunc | 248 |
msispan | 300 |
ne | 652 |
neline | 284 |
pvc | 248 |
scib | 356 |
srate | 300 |
tdm | 276 |
workspace_oplog | 392 |
workspace_paramlog | 236 |
xblconn | 290 |
有了上面的表,要计算出每个存储过程将使用多少逻辑日志空间就容易多了。例如,计算存储过程 BSC_D 的逻辑日志使用情况:
Total logical log usage = 200 * 284 + 600 * 248 + 100 * 276 + 100 * 448 + 100 * 652 + 400 * 392 + 300 * 236 = 618000 (bytes) |
此外,我们还需要加上事务开销(96 字节),检查点(36 字节)和 DPT 开销(取最大值 300 字节)。每当为每次存储过程的执行计算逻辑日志开销时,所有这些开销都要加进来。因此该存储过程的全部逻辑日志开销就是 580500 + 96 +300 = 618396 字节,大约 620 KB (620 KB?)。要获得关于检查点和 DPT 的详细描述,请参考 Administrator's Guide的第 4 章。
下面的表总结了 Move BSC 中涉及的每个存储过程的逻辑日志使用情况:
Move BSC 的逻辑日志使用情况操作名 | 操作次数 | 每次操作使用的日志 | 总共使用的日志(字节) |
bsc_I | 2 | 415880 | 831760 |
bsc_UA | 2 | 165960 | 331920 |
cage_I | 4 | 18720 | 74880 |
cage_UA | 4 | 18720 | 74880 |
slot_I | 64 | 29680 | 1899520 |
gp_func_I | 12 | 15840 | 190080 |
bsc_xcdr_assoc_I | 1 | 3718340 | 3718340 |
te_I | 52 | 41400 | 2152800 |
te_timeslot_I | 637 | 30080 | 19160960 |
gp_func_xcdr_I | 6 | 39500 | 237000 |
nail_I (xcdr) | 2 | 22320 | 44640 |
bsc_D | 2 | 618400 | 1236800 |
cage_D | 4 | 21720 | 86880 |
slot_D | 64 | 27320 | 1748480 |
gp_func_D | 12 | 15840 | 190080 |
bsc_xcdr_assoc_D | 1 | 3713620 | 3713620 |
te_D | 52 | 41400 | 2152800 |
te_timeslot_D | 637 | 24640 | 15695680 |
gp_func_xcdr_D | 6 | 42200 | 253200 |
nail_D | 3 | 22320 | 66960 |
总计 | 1567 | ? | 53861280 |
所以 Move BSC 总共使用的逻辑日志大约是 54 MB。这是一个非常保守的估计。既然 Move BSC 包含了许多的事务,那么很可能在 Move BSC 的运行期间,有些逻辑日志空间会随着某些事务的提交而得到释放,并准备重用。我们配置了 80 个逻辑日志,每个 30 MB 大,长事务高水准线设为 50。这意味着系统上可用的逻辑日志空间是: 80 * 30 / 2 = 1200 MB。最后,我们将所有这些计算综合起来,从而为客户提出了以下公式:
1200 MB - maximum BSC to move * 54 MB => 30MB
其中 30 MB 是一个逻辑日志的大小。根据 Informix Dynamic Server 文档,我们应该总是预留一个空的逻辑日志。因此,如果剩下的逻辑日志记录空间大于 30 MB,那么还是安全的,我们可以自信地说 Move BSC 将会成功,而不会有任何问题,因而每次移动 BSC 的最大数量是:
Maximum BSC to move =< (1200 MB - 30 MB) / 54
移动 BSC 的最大数量是 21,也就是说,如果客户试图一次移动超过 21 个 BSC,那么 Informix Dynamic Server 就会耗尽逻辑日志,而成为长事务,这样反过来就会中止 Move BSC 操作,并冻结 Informix Dynamic Server 引擎。
|
我们的公式有多精确,我们对这样的估计有多大信心呢?让我们测试一下。在这个实验室中,我们在不同机器上进行了三次测试,模拟客户在使用 Move BSC 时的情况。在每次测试之前,我们使用 onstat -l来获得日志空间使用(输出的 Log Space used字段)信息,在每次测试之后,我们再次执行这个命令,然后计算出两者之间的差。这两个数字之间的差就是所使用的实际逻辑日志空间。下面的表显示了测试结果,以 KB 为单元:
Move BSC 测试结果测试 | 描述 | 之前 | 之后 | 实际值 | 预测值 | 精确度 |
1 | 移动 10 个 BSC | 336707980 | 851707980 | 515000000 | 540000000 | 95.37 |
2 | 移动 15 个 BSC | 2198356812 | 2978356812 | 780000000 | 810000000 | 96.30 |
3 | 移动 20 个 BSC | 7035159124 | 8105159124 | 1070000000 | 1080000000 | 99.07 |
上面的测试结果表明,平均来讲,我们的估计大约是真实情况的 95%,还应注意,在预测列的数字总是大于实际列中的数字。这意味着我们对逻辑日志使用的估计是充分的,可靠的。
Jianing Fan 是 Motorola 的一名软件工程师,专门从事关系数据库管理系统。他是 Informix 认证专家和 Oracle 认证专家,作为开发人员、系统管理员和 DBA,他拥有十年以上的数据库和系统经验。可以通过 联系 Jianing 。 |