Ravi VedulaDB2 DBA, Wipro Technologies
2003 年 10 月 本文展示了将 DB2 UDB 历史文件放入一个表中,再以这个表为基础执行管理任务的一种方法。
简介
DB2® Universal Database™ (UDB) 历史文件包含了恢复事件和管理事件的记录,它与 OS/390® 系统下 DB2 中的 SYSIBM.SYSCOPY 表是等效的。除了包含恢复和备份事件之外,历史文件还保存一些 DDL 事件,比如针对表空间和表的 CREATE、 altER、DROP 和 RENAME。对 DB2(OS/390 下)中 SYSIBM.SYSCOPY 表的使用大部分局限于恢复场景和记录对表空间的处理活动这两个方面。DB2 UDB 上的历史文件在以下两点上比 SYSCOPY 表要更胜一筹:
- 它有更细的粒度——在表层次上记录事件。
- 它所记录的事件并不局限于恢复场景,还包括 DDL 类的语句。
然而,如果 LIST HISTORY 输出可以以表的形式来捕捉,而不是以普通输出情况下的文本文件格式来捕捉,那么它就可以使得分析和使用更加容易。在本文中,我将解释如何通过使用您自己的 SYSCOPY 表来做这件事情。
本文介绍 Solaris 和 Linux 下的 DB2 V8.1 Enterprise Server Edition fix pack 1 (single-partition) 服务器 。 可下载的 zip 文件中提供的代码在 Solaris 和 Linux 下的 DB2 V8.1 ESE 上运行良好。
为什么将历史数据放入表中?
DB2 LIST HISTORY 命令的确带有一些参数,这些参数返回特定的信息,但您对给命令的使用还是有些限制。 例如,检索某个对象(假设是 obj1 )自 2003 年 5 月以来的备份的详细信息就不是那么轻松的事情,因为 LIST HISTORY 命令允许您要么指定 SINCE <timestamp> 部分, 要么指定 CONTAINING <object_name> 部分,但是不能同时指定这两部分。
一旦 LIST HISTORY 中的数据被捕捉到一个表中,我们就可以查询该数据,以生成对数据库的管理活动的报告。在联邦服务器群(federated server farm)上,这个表中的数据可以为您提供针对远程数据库的活动的概述。我还将讨论一种备份策略,它不是时间表驱动的(scheduler-driven),而是使用我们的 SYSCOPY 表,并且维护一个用于存储频率信息的驱动表。最后,我们将看一下使用 SYSCOPY 表的日志文件维护。
接下来几节中的例子使用 DB2 命令行来调用脚本。因而这里没有对任何工作或脚本时间表的引用。理想情况下,这些脚本将按照 DBA 通过时间表指定的时间运行。根据数据库上的活动,您可以设置运行频率,使其尽可能接近您想要的实际时间(对于日志归档脚本更应如此,因为当存放活动日志目录的磁盘崩溃时,日志归档脚本对于恢复来说是至关重要的)。
恢复方面在本文中不会涉及。将必需的日志从归档文件路径移到活动目录是恢复过程的一部分,这些日志文件可以从 SYSCOPY 表中识别出来。
SYSCOPY 表的定义和设置
我们将在 DB2 UDB 上使用一个名为 <user>.SYSCOPY 的表来模拟 OS/390 下 DB2 中的 SYSCOPY 表结构。我们将使用一个 perl 脚本格式化来自历史文件的输出,通过这样做就可以用 LIST HISTORY 命令得到的数据来填充这个表。
图 1 展示了 <user>.SYSCOPY 表的描述。在您想在其中分析 LIST HISTORY 输出的那个数据库中创建这个表。
图 1. <user>.SYSCOPY 表
对该表创建以下索引:
- Index1 on (NAME, OBJECT and OPERATION)
- Index2 on (TIME_STAMP DESC)
脚本 syscopy.pl (在可下载的 zip 文件中)填充 <user>.SYSCOPY 表。
用法:
syscopy.pl <dbname> -<full/incremental>
|
传给这个脚本的 -full 参数将检索、格式化和存储 [database origin, current timestamp] 这段时间内的历史文件中的数据,而 -incremental 参数将查询这个表并从历史文件中抽取出自上次运行以来的所有事件。
在备份策略中使用 SYSCOPY
我们将使用一个名为 <user>.BACKUP_CNTRL 的表作为用于管理备份过程的驱动。该表存储备份周期的详细信息,并依靠 <user>.SYSCOPY 表来确定备份类型。脚本 backup_gen.ksh 查询 BACKUP_CNTRL 表,以便为那些适合备份的对象生成和执行备份命令。
图 2 展示了对 <user>.BACKUP_CNTRL 表的描述:
图 2. BACKUP_CNTRL 表
DBA 决定数据库中表空间的备份周期,并在 BACKUP_CNTRL 表中注册它们。 例如,我可以根据磁盘容量和活动模式(即更改)来为某些应用程序表空间草拟一个备份周期,就像这样:
- TS1: 1 次完全在线备份,5 次 delta 备份,1 次增量备份,5 次 delta 备份(然后该周期又从一次完全在线备份重复开始)。
- TS2: 1 次完全在线备份,3 次增量备份。
- TS3: 1 次完全在线备份,2 次 delta 备份。
- TS4: 1 次完全在线备份。
表 1 展示了备份控制表的内容。这里只显示了相关的列, Last_Full 列中的值还没有计算出来。
表 1. BACKUP_CNTRL 表的内容
| Name |
Full |
Delta |
Incremental |
Delta1 |
Last_Full |
| TS1 |
1 |
5 |
1 |
5 |
- (3) |
| TS2 |
1 |
0 |
3 |
0 |
- (1) |
| TS3 |
1 |
2 |
0 |
0 |
- (5) |
| TS4 |
1 |
0 |
0 |
0 |
- (0) |
当 SYSCOPY 表成为当前表时,以下 SQL 为备份控制表的 Last_Full 列生成更新语句,用自上次完全在线/脱机备份以来的天数更新该列:
Set current sqlid = 'db2inst1?
WITH temp_cntrl (name, lf) as
( select name, smallint( current date - date( max(time_stamp) ))
from syscopy
where operation = 'B' and type in ('F', 'N') and name <> ' '
group by name
)
select 'update backup_cntrl set last_full = ', lf, '
where name = '' concat b.name concat ''
from backup_cntrl b, temp_cntrl t
where b.name = t.name ; terminate;
|
如果 Last_Full 备份已经确定(如上表方括号中所示),那么现在所需的备份类型就可以通过以下算法来确定:
注意:对于某个 TS 的 Full、Delta、Incremental 和 Delta1 这些列中的值被记作 vfull、vdelta、vincr 和 vdelta1。 `<-? 是赋值操作符。
- 步骤 1:对备份控制表执行 Select * 选择,将结果放入一个文件中。
- 步骤 2:对于文件中的每个 TSName (记录),检查 last_full >= ( vfull + vdelta + vincr + vdelta1 ) 是否成立。
如果成立: 则最近一次完全备份在完成整个备份周期之前发生。应该强制执行一次完全备份。迭代(从步骤 1开始)。
- 步骤 3:
vfull <- last_full - vfull
vdelta <- last_full - vfull ?vdelta
vincr <- last_full - vfull ?vdelta ?vincr
vdelta1 <- last_full - vfull ?vdelta ?vincr ?vdelta1
- 步骤 4: vfull、vdelta、vincr 和 vdelta1 中第一个出现的负值决定了备份类型。写出用于 TS 的备份命令。迭代。
在实现(可下载 zip 文件中的 shell 脚本 backup_gen.ksh )中,并不是步骤 3 中所有的值都要计算;只要我们碰到了能够决定备份类型的负值,就立即开始迭代。上面的算法决不会更新 BACKUP_CNTRL 表。当该算法结束后,各列值将如表 2 所示:
表 2. 运行脚本之后的 BACKUP_CNTRL 表
| Name |
Full |
Delta |
Incremental |
Delta1 |
Last_Full |
| TS1 |
2 |
-3 |
-4 |
-9 |
3 |
| TS2 |
0 |
0 |
-3 |
-3 |
1 |
| TS3 |
- |
- |
- |
- |
5 |
| TS4 |
-1 |
-1 |
-1 |
-1 |
0 |
注意,对于 TS3 来说 vfull、vdelta、vincr 和 vdelta1 是不确定的。在 TS3 阶段要强制执行一次完全备份。通过阅读上面的表,我们确定对应于 TS1、TS2、TS3 和 TS4 的备份类型分别是 Delta、Incremental、Full 和 Full。
前面的算法为一个给定 TS 确定了备份周期的字符串表示的偏移量。在 TS1 阶段,偏移量(用 粗体显示)就是一个 Delta 备份:
FDD DDDIDDDDD
使用 SYSCOPY 来生成活动报告
有了 SYSCOPY 表中的 LIST HISTORY 数据,我们就可以用一种更简单的方式来跟踪针对系统的活动。例如,我们可以生成一份每日活动报告,就像下面针对某个给定数据库的每日活动报告。
图 3. 示例每日活动报告
下面是生成如图 3 所示的报告的 SQL:
select name as OBJECT,
case operation
when 'A' then 'CrTS'
when 'B' then ' Bkup'
when 'C' then ' LodC'
when 'D' then ' DrpT'
when 'F' then ' RolF'
when 'G' then ' ReoT'
when 'L' then ' Load'
when 'N' then ' RenT'
when 'O' then ' DrTS'
when 'Q' then ' Qsce'
when 'R' then ' Rstr'
when 'T' then ' AlTS'
when 'U' then ' Unld'
else ' Unrecognized OP '
end as OPERATION
from mysyscopy
where date(op_start_time) = current date - 8 days and name <> ' '
group by name, operation ;
|
有了已知的 object、operation 和 op_start_date,我们就可以从 SYSCOPY 表检索 DDL 以获得更详细的信息。
使用 SYSCOPY 来维护数据库日志文件
在本节中,我们将看一个用于维护归档日志文件的方法,该方法没有使用 user-exit,而是使用 SYSCOPY 表中的数据。假设已经为归档日志记录配置了数据库。最早的和当前的日志文件的详细信息都要捕捉到 SYSCOPY 表中。最早日志文件字段可用于日志文件维护。
shell 脚本 logfile_maint.ksh (在 可下载的 zip 文件中)接受三个参数:
- 数据库名
- 一个数值(指定从多少天以前获取最早日志文件)
- 日志文件的归档路径
该脚本为给定的数据库确定日志路径,并为所有比最早日志文件更旧的文件生成日志文件删除命令。此外,如果有任何表空间在经创建日志文件之后 没有采取备份,那么为了保证在稍后需要一个及时的恢复时不会出现恢复错误,该脚本会输出一条警告消息。下面是在名为 `boston' 的服务器上对 `attleboro' 数据库运行 logfile_maint.ksh 脚本的示例。
图 4. logfile_maint.ksh 的运行示例
DBA 可以决定是否运行生成的命令文件,该命令文件根据在警告消息中显示的表空间列表将日志文件从活动日志目录移到指定的归档路径。根据上面的屏幕快照,我可以决定只在对日志文件进行归档之前采取一次 'GLOBALTS' 表空间的备份。
结束语
我们介绍了另一种查询和检索“历史文件”数据的方法,这种方法将数据捕捉到一个表中。然后,我们使用 SYSCOPY 表中的数据得出一个备份策略以及备份对象、报告实用活动和维护日志文件的过程。 |