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 服务器(包括 DB2 ACS 的脚本化接口)、协议文件存储库和客户脚本。DB2 服务器使用备份命令触发快照并调用客户脚本。协议文件存储库获取协议文件,DB2 在这些文件中写入一些重要信息,客户脚本可使用这些信息成功运行快照,尤其是在备份期间必须复制的数据库名称和路径。本文将进一步分析所有这些组件,介绍实例 db2jk1 中的数据库 JK1 的示例。
协议文件和协议文件存储库
协议文件存储库包含操作系统中一个执行快照的目录。它可以是任何提供了以下特权的目录:
该目录必须在启动该命令之前就存在。 拥有数据库的实例的所有者必须能够在此存储库中执行读取和写入操作。 必须有足够的空间来存储操作期间编写的协议文件。
可使用以下命令在 DB2 中运行一个快照备份,以便使用脚本化接口:
BACKUP DATBASE JK1USE SNAPSHOT SCRIPT '$HOME/sqllib/samples/BARVendor/libacssc.sh'OPTIONS '/repository'
CLP 和 ADMIN_CMD 中都可运行此命令:
CALL SYSPROC.ADMIN_CMD("BACKUP DATBASE JK1USE 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 未评估过客户脚本写入的任何信息。如果希望向协议文件写入您自己的选项,最好使用 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.shEXTERNAL_OPTIONS=/repository 2ndoptionDB_NAME=JK1INSTANCE=db2jk1DBPARTNUM=0SIGNATURE=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: OPTIONdo case ${OPTION} in a) action=${OPTARG} ;; c) config=${OPTARG} ;; o) objectId=${OPTARG} ;; t) timestamp=${OPTARG} ;; \?) echo "# Unknown parameter '$1'" esacdone
动作选项 (-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=$_settingcase "$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 操作的动作概述
第一次调用客户脚本时,除了 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=hal9000OBJ_OWNER=OBJ_TYPE=SNAPSHOTOBJ_DB2ID_LEVEL=0OBJ_DB2ID_RELEASE=5OBJ_DB2ID_VERSION=10APP_OPTIONS=1100TIMESTAMP=20130422050024DB2BACKUP_MODE=ONLINEDB2BACKUP_LOGS=INCLUDELOGPATH_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 2ndoptionRC_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=0ACTION=DB2ACS_ACTION_WRITE# cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a snapshot -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg /repository 2ndoptionRC_SNAPSHOT=0# db2ACSSnapshot(): END [Mon Apr 22 05:00:25 2013]# =========================================================
样例客户脚本包装了两个归档文件:一个用于数据路径,另一个用于日志路径(假设它们存在)和日志文件(包括我们指定的文件)。
要创建数据文件的快照,可执行以下步骤。该脚本通过以下步骤接受其选项名称以 DATAPATH 开头的所有路径,并将它们包装在这个 tar 归档文件中:
构造数据文件的文件名:
file="${repository}${db_name}.0.${instance}.${dbpartnum}.${timestamp}.001.tar"
如您所见,该文件名中包含数据库名称、实例名称、分区编号和快照的时间戳。这些名称同样基于通用的 DB2 备份的名称。 将文件名存储在协议文件中:
storeSetting "BACKUP_FILE" $file 构造命令:
cmd="awk -F= '/^DATAPATH/ { print \$2; }' $config | xargs tar -cf $file 2>/dev/null && echo 0 || echo 1" 将该命令写入协议文件中:
echo "# cmd: $cmd" 运行该命令并读取返回代码:
RC=`eval $cmd` 将返回代码写入协议文件中:
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 开头的选项的值:
构造数据文件的文件名
file="${repository}${db_name}.0.${instance}.${dbpartnum}.${timestamp}.log.tar"
该名称类似于数据文件的 tar 文件,但包含字符串 “log” 而不是 “001”。 将文件名存储在协议文件中
storeSetting "BACKUP_FILE" $file 构造命令:
cmd="awk -F= '/^LOGPATH/ { print \$2; }' $config | xargs tar -cf $logs 2>/dev/null && echo 0 || echo 1" 将该命令写入协议文件中:
echo "# cmd: $cmd" 运行该命令并读取返回代码:
RC=`eval $cmd` 将返回代码写入协议文件中:
echo "# tar for logs created, rc=$RC"
清单 5 是一个协议文件的部分内容,显示了快照调用的完整内容,包括样例客户脚本编写的所有注释:
清单 5. 一个协议文件的部分内容
# =========================================================# db2ACSSnapshot(): BEGIN [Mon Apr 22 05:00:23 2013]OBJ_ID=0ACTION=DB2ACS_ACTION_WRITE# cmd: /home/db2jk1/sqllib/samples/BARVendor/libacssc.sh -a snapshot -c /repository/db2acs.JK1.0.db2jk1.1366621223.cfg # /repository 2ndoptionBACKUP_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 includedBACKUP_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=0RC_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=$_settingif [ -f "$file" -a -s "$file" ]
如果指定了包含日志并且日志文件的 tar 文件已经存在,则会使用以下代码解压它:
getSetting "BACKUP_LOGS"logs=$_settinggetSetting "DB2BACKUP_LOGS"includeLogs=$_settingif [ $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=1FIRST_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' existRC_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。