Verify
紧接着的下一个调用是 verify 调用。此调用的用途是检查快照是否成功创建。为了演示整个过程,样例客户脚本使用了以下代码检查所需的
tar 文件是否存在(使用测试选项 –f)和大小是否大于 0(使用测试选项 –s);也就是数据文件的 tar
文件是否存在:
getSetting "BACKUP_FILE" file=$_setting if [ -f "$file" -a -s "$file" ] |
如果指定了包含日志并且日志文件的 tar 文件已经存在,则会使用以下代码解压它:
getSetting "BACKUP_LOGS" logs=$_setting getSetting "DB2BACKUP_LOGS" includeLogs=$_setting if [ $includeLogs = "INCLUDE" ] then if [ -f "$logs" -a -s "$logs" ] |
如果以下某个条件未能得到满足,则会返回 RC_ERROR。
如果一切运行正常,则会生成协议文件中的输出(举例而言)(如清单 6 所示):
清单 6. db2ACSVerify 函数
# ========================================================= # db2ACSVerify(): BEGIN [Mon Apr 22 05:00:25 2013] FIRST_ACTIVE_LOG_ID=1 FIRST_ACTIVE_LOG_CHAIN=0 # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a verify -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg /repository 2ndoption # Backup '/repository/JK1.0.db2jk1.0.20130422050024.001.tar' exist # Logs '/repository/JK1.0.db2jk1.0.20130422050024.log.tar' exist RC_VERIFY=0 # db2ACSVerify(): END [Mon Apr 22 05:00:25 2013] # ========================================================= |
清单 6 包含两个新选项,它们描述了在创建快照期间使用的日志文件 (FIRST_ACTIVE_LOG_ID)
和编写这些日志文件的日志链 (FIRST_ACTIVE_LOG_CHAIN)。在进行还原时,具体来讲是在前滚时,两个选项都是必需的。对样例客户脚本中的
verify 调用的存在性测试的成功消息也包含在内。
如果 verify 调用成功完成,则会调用 storemetadata;如果 verify 调用失败,则会调用
rollback。
Storemetadata
假设 verify 调用返回了 success,下一个调用就是 storemetadata。这是保存在创建快照期间生成的必要附加文件的正确位置;例如,将协议文件保存到备份基础架构是一个不错的主意:更多的信息将会写入其中,但还原将会成功并具有最新状态。
清单 7. db2ACSStoreMetaData 函数
# ========================================================= # db2ACSStoreMetaData(): BEGIN [Mon Apr 22 05:00:25 2013] START_TIME=1366621224 METADATA_SIZE=12364 METADATA_CHECKSUM=20058929 METADATA=... # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a store_metadata -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg /repository 2ndoption RC_STORE_METADATA=0 # db2ACSStoreMetaData(): END [Mon Apr 22 05:00:25 2013] # ========================================================= |
在 清单 7 中,METADATA 选项接受最长的值。它包含编码为 Base64 的 DB2 内存块。这个内存块中的任何更改都会导致快照镜像不可用。要让
DB2 能够在还原期间检查有效性,需要添加 METADATA_CHECKSUM。METADATA_SIZE
描述了这个内存块的大小。
样例客户脚本在此调用期间不执行任何操作。
Rollback
如果 verify 调用在 snapshot 动作期间返回 failure;现在会使用动作 rollback
调用客户脚本,如清单 8 所示。可以在这里清除所有已创建的内容。样例客户脚本从候选协议文件中提取所需的
tar 文件的名称并删除它们。
清单 8. doRollback 函数
doRollback() { getSetting "BACKUP_FILE" oldBackup=$_setting echo "# Delete old backup file : $oldBackup" rm $oldBackup
getSetting "DB2BACKUP_LOGS"
includeLogs=$_setting
if [ $includeLogs = "INCLUDE" ]
then
getSetting "BACKUP_LOGS"
oldLogs=$_setting
echo "# Delete old backup file : $oldLogs"
# Delete old logs file
rm $oldLogs
fi
} |
终止 snapshot 操作
snapshot 操作的所有调用都已完成后,DB2 会终止该会话和操作。它将已完成的操作的返回码 (RC_OPERATION)
添加到协议文件中。如果返回码为 0,那么操作已成功完成,而且镜像可用于还原;其他所有返回码都会导致镜像没有还原资格。
# ========================================================= # db2ACSEndOperation(): BEGIN [Mon Apr 22 05:00:25 2013] RC_OPERATION=0 # db2ACSEndOperation(): END [Mon Apr 22 05:00:25 2013] # ========================================================= # db2ACSTerminate(): BEGIN [Mon Apr 22 05:00:25 2013] # db2ACSTerminate(): END [Mon Apr 22 05:00:25 2013] # ========================================================= |
Restore
还原期间,客户脚本仅被调用了三次:针对 prepare、restore,以及在还原失败时针对 rollback
而调用。以下代码段摘自一个因成功还原的协议文件被忽略而遭遇失败的还原。
请注意,在 restore、query 和 delete 操作期间,会打开两个协议文件,一个描述了当前操作,另一个临时打开的、只读的
协议文件描述了当前考虑的快照镜像。在后续章节中,后一个协议文件被称为候选协议文件。
Prepare
在准备阶段,客户脚本可提供协议文件存储库中额外需要的协议文件。
在调用客户脚本之前,DB2 已提供了需要还原的数据库的一些信息和时间戳,如清单 9 所示。
清单 9. db2ACSBeginOperation 函数
# ========================================================= # db2ACSBeginOperation(): BEGIN [Tue May 21 09:26:54 2013] OPERATION=RESTORE # db2ACSBeginOperation(): END [Tue May 21 09:26:54 2013] # ========================================================= # db2ACSBeginQuery(): BEGIN [Tue May 21 09:26:54 2013] QUERY_TYPE=SNAPSHOT QUERY_DBPARTNUM=0 QUERY_DB=JK1 QUERY_INSTANCE=* QUERY_HOST=* QUERY_OWNER=* QUERY_TIMESTAMP=20130521092650 # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a prepare -c /repository/db2acs.JK1.0.db2jk1.1369142814.cfg /repository RC_PREPARE=0 # db2ACSBeginQuery(): END [Tue May 21 09:26:54 2013] # ========================================================= |
Query
可以向还原命令仅指定时间戳的一部分,例如仅指定日期。DB2 将过滤满足这个部分时间戳的镜像(例如,如果提供了在这一天创建的所有镜像的数据)。候选镜像已在循环的
db2ACSGetNextObject 调用中列出,如下所示:
# ========================================================= # db2ACSGetNextObject(): BEGIN [Tue May 21 09:26:54 2013] RESULT_0_FILE=/repository/db2acs.JK1.0.db2jk1.1369142810.cfg # Timestamp 20130521092650 # db2ACSGetNextObject(): END [Tue May 21 09:26:54 2013] # ========================================================= |
候选协议文件会在这些调用过程中枚举,以便下一个候选协议文件会接受选项 RESULT_1_FILE。
找到最后一个镜像后,您会看到对此函数的一次空调用,随后使用 db2ACSEndQuery 调用结束查询:
# ========================================================= # db2ACSGetNextObject(): BEGIN [Tue May 21 09:26:54 2013] # db2ACSGetNextObject(): END [Tue May 21 09:26:54 2013] # ========================================================= # db2ACSEndQuery(): BEGIN [Tue May 21 09:26:54 2013] # db2ACSEndQuery(): END [Tue May 21 09:26:54 2013] # ========================================================= |
DB2 会选中候选协议文件的最新镜像并还原它。例如,如果您查询 20130521 并且有两个镜像,第一个的创建时间为
201305210900,第二个为 201305211000,那么将还原第二个。
如果选择了候选协议文件,DB2 会从候选协议文件检索元数据并对其解码,如下所示:
# ========================================================= # db2ACSRetrieveMetaData(): BEGIN [Tue May 21 09:26:54 2013] GET_META_OBJ_ID=0 METADATA_DECODED_SIZE=9272 METADATA_CHECKSUM=-1834173632 # db2ACSRetrieveMetaData(): END [Tue May 21 09:26:54 2013] # ========================================================= |
在这些函数运行时,DB2 不会与客户脚本交互。
Restore
在 restore 调用期间,样例客户端脚本解压数据 tar 文件,在必要时也会解压日志 tar 文件。DB2
在完成 restore 调用之前提供了选项 OBJ_ID。借助此编号,需要检索要还原的备份镜像的协议文件:
读取 OBJ_ID:
getSetting "OBJ_ID"objectId=$_setting |
构造要检索的选项:
key="RESULT_${objectId}_FILE" |
从当前要还原的协议文件读取此选项 – 此选项的值是要还原的备份镜像的协议文件名称:
getSetting $keyoldConfig=$_setting |
现在可执行以下步骤:
从候选协议文件读取用于数据文件的 tar 文件的名称:
getSetting "BACKUP_FILE" "" $oldConfig oldBackup=$_setting |
创建命令来解压 tar 文件:
cmd="tar -xf $oldBackup && echo 0 || echo 1" |
将该命令写入协议文件中:
运行该命令并跟踪返回代码:
RC=`eval $cmd` echo "# tar extracted, rc=$RC" |
在还原期间,DB2 在协议文件中提供了选项 ACTION。该选项可接受两个不同的值:DB2ACS_ACTION_READ_BY_OBJECT
和 DB2ACS_ACTION_READ_BY_GROUP。第一个值表示必须还原整个数据库,包括日志文件。第二个值表示只需要还原数据文件。此选项也由样例客户脚本通过以下步骤来处理:
读取此选项:
getSetting "ACTION" readAction=$_setting |
检查值(另外检查对数据文件的解压是否成功完成):
if [ $readAction = "DB2ACS_ACTION_READ_BY_OBJECT" -a $RC -eq 0 ] then |
运行相应的命令来还原日志文件,就像还原数据文件一样:
getSetting "BACKUP_LOGS" "" $oldConfig oldLogs=$_settingcmd="tar -xf $oldLogs && echo 0 || echo 1"echo "# cmd: $cmd"RC=`eval $cmd` |
下面的代码段反映了一个用于还原操作的协议文件中的这些动作:
# ========================================================= # db2ACSSnapshot(): BEGIN [Tue May 21 09:26:54 2013] OBJ_ID=0 ACTION=DB2ACS_ACTION_READ_BY_GROUP # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a restore -c /repository/db2acs.JK1.0.db2jk1.1369142814.cfg /repository # cmd: tar -xf /repository/JK1.0.db2jk1.0.20130521092650.001.tar && echo 0 || echo 1 # tar extracted, rc=0 RC_RESTORE=4 # db2ACSSnapshot(): END [Tue May 21 09:26:54 2013] # ========================================================= |
Rollback
如果 restore 调用失败,就像本示例中一样,DB2 会再次使用动作 rollback 来调用客户脚本。以下代码显示了针对
rollback 动作的调用。还原操作会使用 if 子句检查操作,样例客户脚本在此调用期间也不会执行任何操作。
# ========================================================= # db2ACSEndOperation(): BEGIN [Tue May 21 09:26:54 2013] RC_OPERATION=1 # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a rollback -c /repository/db2acs.JK1.0.db2jk1.1369142814.cfg /repository RC_ROLLBACK=0 # db2ACSEndOperation(): END [Tue May 21 09:26:54 2013] # ========================================================= |
该操作由 DB2 最终终止:
# ========================================================= # db2ACSTerminate(): BEGIN [Tue May 21 09:26:54 2013] # db2ACSTerminate(): END [Tue May 21 09:26:54 2013] # ========================================================= |
Query
您可使用 db2acsutil 从某个协议文件存储库中删除镜像或查询某个协议文件存储库。现在支持以下语法:
db2acsutil script "/home/db2jk1/sqllib/samples/BARVendor/libacssc.sh" options "/repository" query status |
协议文件存储库的规则也可以在 db2acsutil 命令中应用:
如果提供了选项,则始终使用第一个选项作为协议文件存储库。
如果未提供选项,则使用客户脚本的目录。
db2acsutil 的所有可能的标记也受到支持;因此,您可以过滤数据库、实例、主机名、数据库分区号,当然还有时间戳,就像在以下命令中一样:
db2acsutil script "/home/db2jk1/sqllib/samples/BARVendor/libacssc.sh" options "/repository" query status taken at 20130521 database JK1 instance db2jk1 dbpartitionnum 0 show detail |
下面显示了此命令的一种可能结果:
Instance : db2jk1 Database : JK1 Partition : 0 Image timestamp : 20130522051311 Host : hal9000 Owner : DB2 Version : 10.5.0 Creation time : Wed May 22 05:13:11 2013 First active log (chain:file) : 2:13 Metadata bytes : 12364 Progress state : Successful Usability state : Unknown Bytes completed : 0 Bytes total : 0 |
该输出指定了是在哪个实例中的哪个数据库上创建快照以及创建快照的时间。Progress state 在协议文件中的选项
OPERATION 具有值 0 时显示 successful,在选项 OPERATION 为其他任何值时显示
failed,如果协议文件中没有该选项,则显示 in progress。对于脚本化接口创建的镜像,Usability
state 始终显示为 Unknown,因为 DB2 不知道它是否真的可用。
prepare 动作是在 query 操作期间用于调用客户脚本时的惟一动作。在该调用之前提供的信息基本上与其他
prepare 调用期间相同,这可在以下代码中看到:
# ===================================================================== # db2ACSBeginQuery(): BEGIN [Wed May 22 08:17:40 2013] QUERY_TYPE=ALL QUERY_DBPARTNUM=-1 QUERY_DB=* QUERY_INSTANCE=* QUERY_HOST=* QUERY_OWNER=* QUERY_TIMESTAMP=* OPERATION=QUERY # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a prepare -c /home/db2jk1/repository/db2acs.0.1369225060.cfg /home/db2jk1/repository 2ndoption RC_PREPARE=0 # db2ACSBeginQuery(): END [Wed May 22 08:17:40 2013] # ===================================================================== |
prepare 调用可提供协议文件存储库中的协议文件,例如从备份基础架构或其他任何动作还原。prepare
调用未在样例客户脚本中实现。db2ACSBeginQuery 部分已给出了过滤候选协议文件的条件。
随后,DB2 循环所有可用的协议文件,并根据给定条件过滤它们,包括根据操作 SNAPSHOT 过来它们。DB2
考虑的候选协议文件显示在一个协议文件中,例如,在以下代码中:
# ===================================================================== # db2ACSGetNextObject(): BEGIN [Wed May 22 05:13:28 2013] RESULT_2_FILE=/home/db2jk1/repository/db2acs.JK1.0.db2jk1.1369214000.cfg # Timestamp 20130522051322 # db2ACSGetNextObject(): END [Wed May 22 05:13:28 2013] # ===================================================================== |
提供了所有满足条件的候选协议文件的输出。
该操作最终将会关闭,如下所示:
# ===================================================================== # db2ACSGetNextObject(): BEGIN [Wed May 22 08:17:40 2013] # db2ACSGetNextObject(): END [Wed May 22 08:17:40 2013] # ===================================================================== # db2ACSEndQuery(): BEGIN [Wed May 22 08:17:40 2013] # db2ACSEndQuery(): END [Wed May 22 08:17:40 2013] # ===================================================================== # db2ACSTerminate(): BEGIN [Wed May 22 08:17:40 2013] # db2ACSTerminate(): END [Wed May 22 08:17:40 2013] # ===================================================================== |
Delete
也可以使用 db2acsutil,通过以下命令删除使用脚本化接口创建的镜像:
db2acsutil script "$HOME/sqllib/samples/BARVendor/libacssc.sh" options "/repository" query status |
再次声明,所有额外的过滤选项都适用。
使用此命令,用于调用该脚本的第一个动作同样是 prepare,它应该执行与还原或查询期间类似的动作:
# ===================================================================== # db2ACSBeginOperation(): BEGIN [Wed May 22 05:13:28 2013] OPERATION=DELETE # db2ACSBeginOperation(): END [Wed May 22 05:13:28 2013] # ===================================================================== # db2ACSBeginQuery(): BEGIN [Wed May 22 05:13:28 2013] QUERY_TYPE=ALL QUERY_DBPARTNUM=-1 QUERY_DB=SAMPLE QUERY_INSTANCE=* QUERY_HOST=* QUERY_OWNER=* QUERY_TIMESTAMP=* # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a prepare -c /repository/db2acs.0.1369214008.cfg /repository RC_PREPARE=0 # db2ACSBeginQuery(): END [Wed May 22 05:13:28 2013] # ===================================================================== |
执行 prepare 调用后,DB2 再次对所有可用的协议文件执行一次查询,在当前协议文件中列出候选协议文件:
# ===================================================================== # db2ACSGetNextObject(): BEGIN [Wed May 22 05:13:28 2013] RESULT_0_FILE=/repository/db2acs.JK1.0.db2jk1.1369213989.cfg # Timestamp 20130522051311 # db2ACSGetNextObject(): END [Wed May 22 05:13:28 2013] # ===================================================================== |
随后,DB2 再次进入一个循环,对每个要删除的镜像调用 db2ACSDelete,从而导致使用 delete
动作调用客户脚本:
# ===================================================================== # db2ACSDelete(): BEGIN [Wed May 22 05:13:29 2013] DELETE_OBJ_ID=0 # cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a delete -o 0 -t 20130522051311 -c /repository/db2acs.0.1369214008.cfg /repository # Delete old backup file and logs: /repository/SAMPLE.0.db2jk1.0.20130522051311.001.tar # Delete old backup file : /repository/SAMPLE.0.db2jk1.0.20130522051311.log.tar RC_DELETE=4 # db2ACSDelete(): END [Wed May 22 05:13:29 2013] # ===================================================================== |
为了让处理过程更简单,此调用接受另外两个选项,第一个是标记 –o,它提供要在此动作中删除的镜像的对象
ID。此外,还使用 -t 提供了此镜像的时间戳。实质上,样例客户脚本通过以下步骤删除 tar 文件:
构造选项来读取合适的协议文件:
key="RESULT_${objectId}_FILE" |
读取选项并解析值:
getSetting $key oldConfig=$_setting |
从此协议文件中读取数据 tar 文件的名称:
getSetting "BACKUP_FILE" "" $oldConfig oldBackup=$_setting |
删除数据 tar 文件:
读取选项 DB2BACKUP_LOGS 以检查是否包含了日志:
getSetting "DB2BACKUP_LOGS" "" $oldConfig includeLogs=$_setting |
如果包含了日志文件:
if [ $includeLogs = "INCLUDE" ] then |
读取用于日志的 tar 文件的名称:
getSetting "BACKUP_LOGS" "" $oldConfig oldLogs=$_setting |
删除日志文件:
每次成功地为客户脚本调用 delete 动作之后,DB2 都会删除相应的协议文件。
最后,终止 delete 操作,这同样可在协议文件的以下代码段中看到:
# ===================================================================== # db2ACSEndQuery(): BEGIN [Wed May 22 05:13:29 2013] # db2ACSEndQuery(): END [Wed May 22 05:13:29 2013] # ===================================================================== # db2ACSEndOperation(): BEGIN [Wed May 22 05:13:29 2013] RC_OPERATION=0 # db2ACSEndOperation(): END [Wed May 22 05:13:29 2013] # ===================================================================== # db2ACSTerminate(): BEGIN [Wed May 22 05:13:29 2013] # db2ACSTerminate(): END [Wed May 22 05:13:29 2013] # ===================================================================== |
结束语
本文介绍了 DB2 Advanced Copy Services 的新的脚本化接口。文中详细解释了协议文件、客户脚本和每个操作。本系列的后续部分将会分析更多的真实示例。
|