DB2 Advanced Copy Services: 脚本化接口

DB2® Advanced Copy Services 支持获取快照,将这些快照用于 DB2 for Linux®, UNIX® and Windows® 数据库中的备份。客户可通过他们的存储硬件供应商实现的库来使用 DB2 ACS API,也可以自行实现这个 API。此外,客户需要花大量精力才能实现 DB2 ACS 的 C-API。

Joern Klauke, 高级开发工程师, IBM Deutschland Research and Development GmbH

Joern Klauke 是位于伯布林根(德国)的 IBM 研发实验室的 SAP on DB2 for Linux, UNIX, and Windows 软件开发人员。他在 IBM 拥有 5 年帮助 DB2 LUW 客户实现最佳实践、分析问题和排除故障的经验。他拥有哈雷马丁-路德大学(德国)的计算机科学学位。



Martin Jungfer, 软件工程师, IBM Deutschland Research and Development GmbH

Martin Jungfer 在 SAP 环境中管理 DB2 for Linux, UNIX, and Windows 方面拥有多年的经验和深厚知识。



2014 年 3 月 06 日

简介

DB2 10.5 为 DB2 Advanced Copy Services (DB2 ACS 引入了一个称为脚本化接口 (scripted interface) 的新功能。该功能使得客户能够实现 shell 脚本而不是 C 库,这些脚本可使用存储供应商提供的工具运行快照操作。您可以在存储硬件中独立使用脚本化接口。此外,DB2 支持新上市的存储硬件。

该功能支持 DB2 的所有三种架构:企业服务器、使用数据库分区功能 (DPF) 的多分区 (multipartitioned) 数据库,以及使用 pureScale 的数据库。所有 UNIX 和 Linux 平台(只要 DB2 通过了它们的认证)都支持它。

本文章系列将介绍此功能,后续文章还会提供一些真实示例。本文将详细介绍组成该功能的各个部分。所给出的常规设置基于 DB2 所提供的样例客户脚本的示例。

图 1 给出了 DB2 ACS 新的脚本化接口的总体结构:

图 1. DB2 ACS 的新脚本化接口的结构
DB2 ACS 的新脚本化接口的结构

您可看到此功能的三个重要部分:DB2 服务器(包括 DB2 ACS 的脚本化接口)、协议文件存储库和客户脚本。DB2 服务器使用备份命令触发快照并调用客户脚本。协议文件存储库获取协议文件,DB2 在这些文件中写入一些重要信息,客户脚本可使用这些信息成功运行快照,尤其是在备份期间必须复制的数据库名称和路径。本文将进一步分析所有这些组件,介绍实例 db2jk1 中的数据库 JK1 的示例。


协议文件和协议文件存储库

协议文件存储库包含操作系统中一个执行快照的目录。它可以是任何提供了以下特权的目录:

  • 该目录必须在启动该命令之前就存在。
  • 拥有数据库的实例的所有者必须能够在此存储库中执行读取和写入操作。
  • 必须有足够的空间来存储操作期间编写的协议文件。

可使用以下命令在 DB2 中运行一个快照备份,以便使用脚本化接口:

BACKUP DATBASE JK1
USE SNAPSHOT SCRIPT '$HOME/sqllib/samples/BARVendor/libacssc.sh'
OPTIONS '/repository'

CLP 和 ADMIN_CMD 中都可运行此命令:

CALL SYSPROC.ADMIN_CMD("BACKUP DATBASE JK1
USE SNAPSHOT SCRIPT '$HOME/sqllib/samples/BARVendor/libacssc.sh'
OPTIONS '/repository'")

在此命令中,$HOME/sqllib/samples/BARVendor/libacssc.sh 是客户脚本的位置和名称;这是 DB2 所提供的样例客户脚本。/repository 是协议文件存储库的目录。请注意,您必须对脚本名称和存储库使用绝对路径。如果未提供存储库,则会查找客户脚本所在的目录,将它用作协议文件存储库。如果希望为客户脚本提供更多的选项,可以使用 OPTIONS 子句,因为第一个参数始终会解析为协议文件存储库。

协议文件具有以下两个用途:

  • 提供 DB2 还原所必需的数据库信息。因此,备份这些文件也是一个不错的想法。
  • 提供备份进度信息,将它们用于调查分析用途(例如,每个函数和用于调用该脚本的以 “# cmd:” 开头的命令的开始和结束时间戳)

DB2 生成的每个协议文件的名称具有图 2 中所示的结构:

图 2. DB2 生成的协议文件名称
DB2 生成的协议文件名称

DB2 和客户脚本都将信息写入协议文件,但目前 DB2 未评估过客户脚本写入的任何信息。如果希望向协议文件写入您自己的选项,最好使用 USER 作为命令前缀,以避免未来与新 DB2 选项发生冲突。DB2 使用名称-值对作为选项,它们是用 = 符号分隔的。

在每个操作期间,会编写一个新协议文件。无论成功还是失败,备份操作的协议文件都会保留。失败备份的协议文件必须从存储库中手动删除,以避免在还原操作期间出现问题。其他操作(比如删除、查询或还原)的协议文件仅在失败时才保留。您应该在完成调查分析后删除它们。

协议文件被划分为反映对 DB2 ACS API 的函数调用的不同部分。每一部分以一个时间戳开始和结束,表明每次调用花费了多长时间。此外,该信息还会在 DB2 ACS API 在该函数调用期间提供的每一部分中提供。以下代码显示了来自一个备份操作的协议文件的 db2ACSBeginOperation 调用:

# =========================================================
# db2ACSBeginOperation(): BEGIN [Mon Apr 22 05:00:23 2013]
OPERATION=SNAPSHOT
# db2ACSBeginOperation(): END [Mon Apr 22 05:00:23 2013]
# =========================================================

您可以看到函数的名称、两个时间戳和指定的操作(在本例中为 snapshot)。

对于后续部分,将使用目录 /repository 作为协议文件存储库。

所有操作的协议文件都以一个通用的 db2ACSInitialize 函数部分开始,类似于清单 1:

清单 1. db2ACSInitialize 函数
# =========================================================
# db2ACSInitialize(): BEGIN [Mon Apr 22 05:00:23 2013]
EXTERNAL_SCRIPT=/home/db2jk1/sqllib/samples/BARVendor/libacssc.sh
EXTERNAL_OPTIONS=/repository 2ndoption
DB_NAME=JK1
INSTANCE=db2jk1
DBPARTNUM=0
SIGNATURE=SQL10050
# db2ACSInitialize(): END [Mon Apr 22 05:00:23 2013]
# =========================================================

如您所见,这段代码指定了命令发出的数据库名称、实例名称和实例版本(也就是 SIGNATURE)。这段代码摘自一个 snapshot 操作。


详细分析样例客户脚本

下一节将详细介绍在每个操作期间样例客户脚本执行了哪些动作 (action)。

每次调用都类似于以下调用:

/home/db2jk1/sqllib/samples/BARVendor/libacssc.sh
–a prepare 
–c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg
/repository 2ndoption

标记 –a 后跟要在该调用中执行的动作;标记 –c 后跟当前使用的协议文件。BACKUP 命令的 OPTIONS 子句中提供的选项附加到脚本命令中。每个命令也会由 DB2 写入到协议文件中。

前面已经提到过,DB2 提供了一个样例客户脚本来演示该实例路径 $HOME/sqllib/samples/BARVendor 中的名称 libacssc.sh 的结构和可能的用法。后续几个小节中的示例都会使用此脚本。此脚本在以下行调用选项时会立即解析这些选项:

while getopts a:c:o:t: OPTION
do
   case ${OPTION} in
      a) action=${OPTARG}
         ;;
      c) config=${OPTARG}
         ;;
      o) objectId=${OPTARG}
         ;;
      t) timestamp=${OPTARG}
         ;;
      \?) echo "# Unknown parameter '$1'"
   esac
done

动作选项 (-a) 调用 shell 脚本中的相应函数,如下面的代码段中所示,其中以 do 开头的字符串是函数的名称:

case "$action" in
   prepare)
      doPrepare
      ;;
   snapshot)
      doSnapshot
      ;;
   restore)
      doRestore
      ;;
   delete)
      doDelete
      ;;
   verify)
      doVerify
      ;;
   store_metadata)
      doStoreMetaData
      ;;
   rollback)
      doRollback
      ;;
esac

客户脚本可在执行多个操作期间支持一些动作。例如,prepare 动作会在所有操作(包括 snapshot、restore、query 和 delete)执行期间发生。出于这个目的,对这些动作的调用应拥有以下结构,这样才能对不同的操作运行不同的步骤:

getSetting "OPERATION"
operation=$_setting
case "$operation" in
 snapshot)
 ...
 ;;
 delete)
 ...
 ;;
 restore)
 ...
 ;;
 query)
 ...
 ;;
esac

每个动作都以一个返回代码结束,该代码由 DB2 写入协议文件,并拥有通用前缀 RC_;如果 prepare 动作在客户脚本中由 exit 1 终止,那么 DB2 会将 RC_PREPARE=4 写入协议文件中。

样例客户脚本包含两个帮助函数。函数 getSetting 从协议文件中返回一个选项。该函数中最重要的一行如下:

cmd="awk -F= '/^${1}/ { print \$2 }' $useConfig | head -1"

它借助 UNIX 工具 awk 读取完整的协议文件,并通过解析获得键的指定名称。该值由 = 符号分隔。head -1 将所返回的值的数量限制到第一个。

第二个函数 storeSetting 将选项写入协议文件中,并用 “=” 符号分隔它们,这使得在协议文件中保持此语法变得更容易。它通过以下代码完成此任务:

echo "$1=$2"

通常,客户脚本中使用的每个没有目标的 echo 命令的输出都会写入协议脚本中。如果希望使用另一个文件保存调试信息,可以向 echo 命令附加一个目标:

echo "$1=$2" >> target_file

Snapshot

在 snapshot 操作期间,会调用客户脚本 4 次,分别为 prepare、snapshot、verify 和(依赖于 verify 调用的结果)storemetadata 或 rollback。图 3 概述了 snapshot 操作的动作:

图 3. snapshot 操作的动作概述
snapshot 操作的动作概述

第一次调用客户脚本时,除了 db2ACSInitialize 调用提供的信息之外,清单 2 中的信息已写入协议文件中,如图 3 所示:

清单 2. 第一次调用的客户脚本
# =========================================================
# db2ACSBeginOperation(): BEGIN [Mon Apr 22 05:00:23 2013]
OPERATION=SNAPSHOT
# db2ACSBeginOperation(): END [Mon Apr 22 05:00:23 2013]
# =========================================================
# db2ACSPartition(): BEGIN [Mon Apr 22 05:00:23 2013]
OBJ_HOST=hal9000
OBJ_OWNER=
OBJ_TYPE=SNAPSHOT
OBJ_DB2ID_LEVEL=0
OBJ_DB2ID_RELEASE=5
OBJ_DB2ID_VERSION=10
APP_OPTIONS=1100
TIMESTAMP=20130422050024
DB2BACKUP_MODE=ONLINE
DB2BACKUP_LOGS=INCLUDE
LOGPATH_PRIMARY=/home/db2jk1/db2jk1/NODE0000/SQL00001/LOGSTREAM0000/
DATAPATH_DB=/home/db2jk1/db2jk1/NODE0000/SQL00001/MEMBER0000/
DATAPATH_LOCAL_DB=/home/db2jk1/db2jk1/NODE0000/sqldbdir/
DATAPATH_DB=/home/db2jk1/db2jk1/NODE0000/SQL00001/
DATAPATH_AUTOSTORAGE=/home/db2jk1/db2jk1/NODE0000/JK1/
# db2ACSPartition(): END [Mon Apr 22 05:00:23 2013]
# =========================================================

其中,最重要的选项以 DATAPATH 或 LOGPATH 开头;它们显示了必须包含在快照中的路径和日志目录。可以看到,它们还显示了数据路径的类型,例如自动存储路径 (DATAPATH_AUTOSTORAGE) 和数据库路径 (DATAPATH_DB)。同样地,日志目录被指定为 LOGPATH_PRIMARY(主要日志路径)和 LOGPATH_MIRROR(镜像日志路径,如果存在)。当然,只有必须在快照中包含日志时(就像本例中一样),才会提供日志路径。关于协议文件中可能包含的键名称的完整列表,请参阅 DB2 10.5 数据中心的 DB2 ACS 协议文件部分所示的表。

选项 DB2BACKUP_MODE 可以接受值 ONLINE 和 OFFLINE,用它们来反映在线或离线快照。默认值为 OFFLINE。DB2BACKUP_LOGS 接受值 INCLUDE 或 EXCLUDE,具体情况取决于在 DB2 backup 命令中指定了包含还是排除日志。默认值为 INCLUDE(ONLINE 和 OFFLINE 备份都是如此)。

Prepare

将此信息写入协议文件后,就会使用动作 prepare 第一次调用客户脚本:

清单 3. 使用动作 prepare 第一次调用客户脚本
# =========================================================
# db2ACSPrepare(): BEGIN [Mon Apr 22 05:00:23 2013]
# cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh
   -a prepare
   -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg
   /repository 2ndoption
RC_PREPARE=0
# db2ACSPrepare(): END [Mon Apr 22 05:00:23 2013]
# =========================================================

在这之后,下一个调用是 snapshot 调用。在此调用之前,如果快照已在线,那么数据库的 write 操作是挂起的;也就是说 WRITE SUSPEND 会自动在数据库上设置。因此,prepare 调用是准备文件系统,检查存储系统的空间需求和实际创建快照之前执行其他操作的正确位置。样例客户脚本在该调用期间未执行任何操作。

Snapshot

现在已准备就绪,DB2 可调用该脚本来实际创建快照了。再次声明,在调用之前,如果备份模式为 ONLINE,那么 DB2 会将数据库设置为 WRITE SUSPEND 模式。如果指定了排除日志,对日志文件执行的写入将会继续执行(有关 SET WRITE 命令的更多信息,请参阅 DB2 信息中心)。如果客户脚本未向协议文件写入任何信息,db2ACSSnapshot 部分将类似于清单 4:

清单 4. db2ACSSnapshot 函数
# =========================================================
# db2ACSSnapshot(): BEGIN [Mon Apr 22 05:00:23 2013]
OBJ_ID=0
ACTION=DB2ACS_ACTION_WRITE
# cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh 
 -a snapshot 
 -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg
   /repository 2ndoption
RC_SNAPSHOT=0
# db2ACSSnapshot(): END [Mon Apr 22 05:00:25 2013]
# =========================================================

样例客户脚本包装了两个归档文件:一个用于数据路径,另一个用于日志路径(假设它们存在)和日志文件(包括我们指定的文件)。

要创建数据文件的快照,可执行以下步骤。该脚本通过以下步骤接受其选项名称以 DATAPATH 开头的所有路径,并将它们包装在这个 tar 归档文件中:

  1. 构造数据文件的文件名:
    file="${repository}${db_name}.0.${instance}.${dbpartnum}.${timestamp}.001.tar"

    如您所见,该文件名中包含数据库名称、实例名称、分区编号和快照的时间戳。这些名称同样基于通用的 DB2 备份的名称。
  2. 将文件名存储在协议文件中:
    storeSetting "BACKUP_FILE" $file
  3. 构造命令:
    cmd="awk -F= '/^DATAPATH/ { print
                   \$2; }' $config | xargs tar -cf $file 2>/dev/null && echo 0 ||
                   echo 1"
  4. 将该命令写入协议文件中:
    echo "# cmd:
                   $cmd"
  5. 运行该命令并读取返回代码:
    RC=`eval
                   $cmd`
  6. 将返回代码写入协议文件中:
    echo "#
                   backup tar created, rc=$RC"

现在,该脚本必须处理日志文件。首先,它读取相应选项的值来确定是否必须包含日志文件:

getSetting "DB2BACKUP_LOGS"
includeLogs=$_setting

然后根据此结果执行动作:

if [ $includeLogs = "INCLUDE" ]
then
   echo "# Logs to be included"

日志文件的 tar 归档文件的名称的构造方式与数据路径的 tar 文件的 tar 名称相同,同样存储在协议文件中。日志文件的 tar 文件的包装方式也与数据路径的 tar 文件相同,但这一次接受的是以 LOGPATH 开头的选项的值:

  1. 构造数据文件的文件名
    file="${repository}${db_name}.0.${instance}.${dbpartnum}.${timestamp}.log.tar"

    该名称类似于数据文件的 tar 文件,但包含字符串 “log” 而不是 “001”。
  2. 将文件名存储在协议文件中
    storeSetting "BACKUP_FILE" $file
  3. 构造命令:
    cmd="awk -F= '/^LOGPATH/ { print \$2; }' $config |
                     xargs tar -cf $logs 2>/dev/null && echo 0 || echo 1"
  4. 将该命令写入协议文件中:
    echo "# cmd: $cmd"
  5. 运行该命令并读取返回代码:
    RC=`eval $cmd`
  6. 将返回代码写入协议文件中:
    echo "# tar for logs created, rc=$RC"

清单 5 是一个协议文件的部分内容,显示了快照调用的完整内容,包括样例客户脚本编写的所有注释:

清单 5. 一个协议文件的部分内容
# =========================================================
# db2ACSSnapshot(): BEGIN [Mon Apr 22 05:00:23 2013]
OBJ_ID=0
ACTION=DB2ACS_ACTION_WRITE
# cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh
 -a snapshot
 -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg 
# /repository 2ndoption
BACKUP_FILE=/repository/JK1.0.db2jk1.0.20130422050024.001.tar
# cmd: awk -F= '/^DATAPATH/ { print $2; }' 
 /repository/db2acs.JK1.0.db2jk1.1366621223.cfg | 
 xargs tar -cf 
 /repository/JK1.0.db2jk1.0.20130422050024.001.tar 
   2>/dev/null && echo 0 || echo 1
# backup tar created, rc=0
# Logs to be included
BACKUP_LOGS=/repository/JK1.0.db2jk1.0.20130422050024.log.tar
# cmd: awk -F= '/^LOGPATH/ { print $2; }' 
 /repository/db2acs.JK1.0.db2jk1.1366621223.cfg
 | xargs tar -cf 
 /repository/JK1.0.db2jk1.0.20130422050024.log.tar 
   2>/dev/null && echo 0 || echo 1
# tar for logs created, rc=0
RC_SNAPSHOT=0
# db2ACSSnapshot(): END [Mon Apr 22 05:00:25 2013]
# =========================================================

在客户脚本完成快照动作并将控制权返回给 DB2 后,会立即再次允许执行数据库的 write 操作;也就是说,如果备份模式为 ONLINE,则会自动设置 WRITE RESUME。

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。借助此编号,需要检索要还原的备份镜像的协议文件:

  1. 读取 OBJ_ID:
    getSetting "OBJ_ID"objectId=$_setting
  2. 构造要检索的选项:
    key="RESULT_${objectId}_FILE"
  3. 从当前要还原的协议文件读取此选项 – 此选项的值是要还原的备份镜像的协议文件名称:
    getSetting $keyoldConfig=$_setting

现在可执行以下步骤:

  1. 从候选协议文件读取用于数据文件的 tar 文件的名称:
    getSetting "BACKUP_FILE" "" $oldConfig
    oldBackup=$_setting
  2. 创建命令来解压 tar 文件:
    cmd="tar -xf $oldBackup && echo 0 || echo 1"
  3. 将该命令写入协议文件中:
    echo "# cmd: $cmd"
  4. 运行该命令并跟踪返回代码:
    RC=`eval $cmd`
    echo "# tar extracted, rc=$RC"

在还原期间,DB2 在协议文件中提供了选项 ACTION。该选项可接受两个不同的值:DB2ACS_ACTION_READ_BY_OBJECT 和 DB2ACS_ACTION_READ_BY_GROUP。第一个值表示必须还原整个数据库,包括日志文件。第二个值表示只需要还原数据文件。此选项也由样例客户脚本通过以下步骤来处理:

  1. 读取此选项:
    getSetting "ACTION"
    readAction=$_setting
  2. 检查值(另外检查对数据文件的解压是否成功完成):
    if [ $readAction = "DB2ACS_ACTION_READ_BY_OBJECT" -a $RC -eq 0 ]
    then
  3. 运行相应的命令来还原日志文件,就像还原数据文件一样:
    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 文件:

  1. 构造选项来读取合适的协议文件:
    key="RESULT_${objectId}_FILE"
  2. 读取选项并解析值:
    getSetting $key
    oldConfig=$_setting
  3. 从此协议文件中读取数据 tar 文件的名称:
    getSetting "BACKUP_FILE" "" $oldConfig
    oldBackup=$_setting
  4. 删除数据 tar 文件:
    rm $oldBackup
  5. 读取选项 DB2BACKUP_LOGS 以检查是否包含了日志:
    getSetting "DB2BACKUP_LOGS" "" $oldConfig
    includeLogs=$_setting
  6. 如果包含了日志文件:
    if [ $includeLogs = "INCLUDE" ]
    then
  7. 读取用于日志的 tar 文件的名称:
    getSetting "BACKUP_LOGS" "" $oldConfig
    oldLogs=$_setting
  8. 删除日志文件:
    rm $oldLogs

每次成功地为客户脚本调用 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 的新的脚本化接口。文中详细解释了协议文件、客户脚本和每个操作。本系列的后续部分将会分析更多的真实示例。

参考资料

学习

获得产品和技术

  • 使用 IBM 试用软件 构建您的下一个开发项目,这些软件可直接从 developerWorks 下载获得。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=964995
ArticleTitle=DB2 Advanced Copy Services: 脚本化接口
publish-date=03062014