DB2 10.5 为 DB2 Advanced Copy Services (DB2 ACS) 引入了一个名为脚本化接口 (scripted interface) 的新功能。该功能使得客户能够实现 shell 脚本,而不是 C 库。这些脚本可使用存储供应商提供的工具来运行快照操作 (operation)。脚本化接口的使用可独立于您的存储硬件。此外,在存储硬件上市后,DB2 会迅速提供这方面的支持。
该功能支持 DB2 的所有 3 种架构:企业服务器、使用数据库分区功能 (DPF) 的多分区数据库,以及使用 pureScale 的数据库。在所有通过了 DB2 认证的 UNIX 和 Linux 平台上都支持它。
本系列文章介绍了这项功能,后续文章将会提供一些真实的示例。这是本系列的第二篇文章,将会使用 Linux LVM 演示脚本化接口。
LVM 是用于 Linux 操作系统的逻辑卷管理器(Logical Volume Manager)。除了这些功能之外,它还支持逻辑卷的快照。本文将介绍如何借助 DB2 ACS 脚本化接口捕获 DB2 数据库备份的快照。
Linux LVM 是一个 Linux 内核扩展,它在存储硬件之上引入了一个抽象层。这提高了存储管理的灵活性;例如,它简化了分区的调整。此外,LVM 允许捕获 LVM 卷组中的分区的快照。
本文使用了图 1 中所示的布局:
图 1. 逻辑卷组
在图 1中,您可以看到物理卷 /dev/sdb 。LVM 卷组 data 用完了整个物理卷。卷组 data 包含逻辑卷 joern 、 data1 、 data2 和 logs 。这个卷组中仍然有空闲空间,将被用于捕获这些逻辑卷的快照。逻辑卷使用 ext4 文件系统格式化。
逻辑卷按表 1 中所示进行挂载:
表 1. 挂载的逻辑卷
逻辑卷 | 挂载点 | 用途 |
---|---|---|
/dev/data/joern | /db2/joern | 数据库目录 |
/dev/data/data1 | /db2/data1 | 自动存储路径 1 |
/dev/data/data2 | /db2/data2 | 自动存储路径 2 |
/dev/data/logs | /db2/logs | 数据库日志 |
表 2 简短概述了本文中提及的用于 LVM 实用程序的命令,其中还指出了这些命令的用途:
表 2. 命令概述
命令 | 用途 |
---|---|
lvdisplay | 显示逻辑卷的信息。具体来讲,选项 –c 用于获取冒号分隔的信息列表,包括大小。关于所包含的列的概述,请查看手册页。 |
lvcreate | 在一个卷组中创建逻辑卷。该命令还用于为包含存储路径和日志路径的逻辑卷创建快照卷。 |
lvconvert | 将快照回禀会包含存储和日志路径的逻辑卷中;也就是说,可将它用于还原快照。 |
lvchange | 更改一个逻辑卷的属性。在某些情况下,有必要取消激活并再次激活逻辑卷,以便成功完成合并。 |
lvremove | 删除逻辑卷,在删除镜像期间使用。 |
vgdisplay | 查询卷组的信息。具体来讲,选项 –c 用于获取冒号分隔的信息列表,包括大小。关于所包含的列的概述,请查看手册页。 |
LVM 快照使用 lvcreate 命令和 –s 选项创建。LVM 可处理写入时复制;也就是说,在首次更改原始卷上的一个数据块时,该数据块的原始内容的镜像会写入到快照中。最后,该快照仅包含原始卷中更改的数据块,但包含的是在创建该快照时这些数据块所拥有的内容。这可能是很少量的数据。但是因为我们还希望能够还原丢弃的数据库,所以我们建议让快照逻辑卷的大小等于原始卷。如果某个 LVM 快照卷空间不足,那么 Linux 会停止对其执行写入操作,这进而会损坏快照备份镜像。
该脚本化接口调用的客户脚本需要借助实例所有者的特权来运行。通常,此用户不允许运行更改 LVM 配置的命令。
在本文中,运行这些命令的特权是使用 sudo 授予的。这些命令可使用命令 visudo 添加到 sudo 配置中,为使用的每个命令添加以下行:
jklauke ALL=NOPASSWD: /sbin/lvdisplay
这样,用户无需在使用该命令时输入根密码。
对于其他平台,可能还有其他解决方案;例如,将实例所有者添加到允许使用合适的命令的分组中。我们不鼓励使用设置了 setuid 位的脚本。
本节提供一段客户脚本的示例实现,该脚本使用了 Linux LVM 的创建、使用和删除快照的能力。
在这个客户脚本中,需要频繁地使用以下循环:
110 for i in `grep "^DATAPATH" $config | / 111 awk -F= '{print $2}' | / 112 xargs -I/{/} df /{/} | / 113 grep '^/dev' | / 114 awk '{print $1;}' | / 115 uniq ` 116 do
这为您提供了需要在执行快照期间备份的一组逻辑卷。该命令执行以下步骤:
DATAPATH=/db2/joern
DATAPATH=path
中等号后的部分(第 111 行): /db2/joern
Filesystem 1K-blocks Used Available
Use% Mounted on/dev/mapper/data-joern 2064208 268980 1690372 14% /db2/joern
/dev/mapper/data-joern 2064208 268980 1690372
14% /db2/joern
/dev/mapper/data-joern
/dev/mapper/data-joern
本文剩余内容将会详细介绍 备份 、 还原 和 删除 操作。这些操作的动作 (action) 已在本文章系列的第 1 部分 中介绍。对于备份,这些动作包括:准备、快照、验证、依赖于验证调用的结果,以及存储元数据或回滚。
再一次声明,我们建议将快照卷的大小设置为与原始卷相同。
LVM 脚本中的 准备 动作的目的是确定每个卷组中是否拥有足够的空闲空间,以便能够将每个逻辑卷都备份到它的卷组中。为此,我们实现了 doPrepare() 函数,如清单 1 所示:
清单 1. doPrepare() 函数代码
65 doPrepare() { 66 # 67 # P R E P A R E 68 # 69 # -------------------------------------- 70 getSetting "OPERATION" 71 operation=$_setting 72 if [ $operation = "SNAPSHOT" ] 73 then 74 for group in `sudo vgdisplay -c | awk -F: '{print $1}'` 75 do 76 freespace=`sudo vgdisplay -c $group | / 77 awk -F":" '{print $16}'` 78 cmd="egrep '^DATAPATH|^LOGPATH' $config | / 79 awk -F= '{print /$2}' | / 80 xargs -I/{/} df /{/} | / 81 grep '^/dev' | / 82 awk '{print /$1}' | / 83 uniq | / 84 xargs -I/{/} sudo lvdisplay -c /{/} | / 85 awk -F: -v c=$group '/$2==c { SUM += /$8 } END {print SUM}'" 86 87 echo "# cmd: "$cmd 88 neededspace=`eval $cmd` 89 90 if [ $neededspace -gt $freespace ] 91 then 92 echo "# Goup: " $group 93 echo "# Freespace: " $freespace 94 echo "# Needed Space: " $neededspace 95 RC=$RC_NOT_ENOUGH_SPACE 96 break 97 fi 98 done 99 fi 100 # -------------------------------------- 101 }
函数 doPrepare() 将执行以下步骤:
现在我们已确定拥有足够的空间,我们将使用函数 doSnapshot() 获取一个快照,如清单 2 所示:
清单 2. doSnapshot() 函数代码
103 doSnapshot() { 104 # 105 # S N A P S H O T 106 # 107 # -------------------------------------- 108 getSetting "TIMESTAMP" 109 timestamp=$_setting 110 for i in `grep "^DATAPATH" $config | / 111 awk -F= '{print $2}' | / 112 xargs -I/{/} df /{/} | / 113 grep '^/dev' | / 114 awk '{print $1;}' | / 115 uniq ` 116 do 117 vol=`sudo lvdisplay -c $i | awk -F: '{print $1;}'| tr -d ' '` 118 echo "USER_VOLUME_DATA="$vol 119 snapName=`basename $vol`"_snap_"$timestamp 120 sudo lvcreate -s -n $snapName -l100%ORIGIN $vol 121 done 122 getSetting "DB2BACKUP_LOGS" 123 includeLogs=$_setting 124 if [ $includeLogs = "INCLUDE" -a $RC -eq 0 ] 125 then 126 for i in `grep "^LOGPATH" $config | / 127 awk -F= '{print $2}' | / 128 xargs -I/{/} df /{/} | / 129 grep '^/dev' | / 130 awk '{print $1;}' | / 131 uniq ` 132 do 133 vol=`sudo lvdisplay -c $i | awk -F: '{print $1;}'| tr -d ' '` 134 echo "USER_VOLUME_LOG="$vol 135 snapName=`basename $vol`"_snap_"$timestamp 136 sudo lvcreate -s -n $snapName -l100%ORIGIN $vol 137 done 138 fi 139 # -------------------------------------- 140 }
此命令的选项如下所示:
在前几步中,获取了 data 逻辑卷的快照。现在我们需要获取日志卷的快照。首先确定这是否有必要这样做(第 122 到 125 行)。
以下行对日志卷执行了与数据卷相同的操作:确定逻辑卷,使用前缀 USER_VOLUME_LOG 存储逻辑卷,以便将它用于还原之用途,并运行快照(第 126 到 137 行)。
清单 3. doVerify() 函数代码
238 doVerify() { 239 # 240 # V E R I F Y 241 # 242 # -------------------------------------- 243 mkdir /tmp/verify 244 getSetting "TIMESTAMP" "" $oldConfig 245 timestamp=$_setting 246 for i in `grep "^USER_VOLUME_DATA" $config | / 247 awk -F= '{print $2}'` 248 do 249 vol=$i"_snap_"$timestamp 250 sudo mount $vol /tmp/verify 251 $RC=$? 252 sudo umount /tmp/verify 253 if [ $RC -neq 0 ] 254 then 255 echo "# Mounting of $vol failed" 256 break 257 fi 258 echo "# Volume $i checked" 259 done 260 getSetting "DB2BACKUP_LOGS" 261 includeLogs=$_setting 262 if [ $includeLogs = "INCLUDE" -a $RC -eq 0 ] 263 then 264 for i in `grep "^USER_VOLUME_LOG" $config | / 265 awk -F= '{print $2}'` 266 do 267 vol=$i"_snap_"$timestamp 268 sudo mount $vol /tmp/verify 269 $RC=$? 270 sudo umount /tmp/verify 271 if [ $RC -neq 0 ] 272 then 273 echo "# Mounting of $vol failed" 274 break 275 fi 276 echo "# Volume $i checked" 277 done 278 fi 279 rmdir /tmp/verify 280 # -------------------------------------- 281 }
为了确定快照是否已成功捕获,该脚本会尝试挂载每个快照的逻辑卷,检查此操作是否成功,然后再次卸载它。具体而言,该脚本将运行以下步骤:
如果需要包含日志文件,该脚本必须检查这些卷的快照是否成功:
最后,删除临时目录(第 280 行)。
如果在 验证 动作期间出现错误,也就是说,如果至少一个快照卷未能挂载,那么下一个要调用的动作将是 回滚 。此过程的实现如清单 4 所示:
清单 4. doRollback() 函数代码
295 doRollback() { 296 # 297 # R O L L B A C K 298 # 299 # -------------------------------------- 300 getSetting "OPERATION" 301 operation=$_setting 302 if [ $operation = "SNAPSHOT" ] 303 then 304 for i in `grep "^VOLUME_DATA" $config | / 305 awk -F= '{print $2}'` 306 do 307 sudo lvremove $i_snap_$timestamp 308 done 309 getSetting "DB2BACKUP_LOGS" 310 includeLogs=$_setting 311 if [ $includeLogs = "INCLUDE" -a $RC -eq 0 ] 312 then 313 for i in `grep "^VOLUME_LOG" $config | / 314 awk -F= '{print $2}'` 315 do 316 sudo lvremove $i_snap_$timestamp 317 done 318 fi 319 fi 320 # -------------------------------------- 321 }
基本来讲,回滚会运行以下步骤来删除已存在的所有快照:
Storemetadata 不执行任何命令。Storemetadata 可将协议文件保存到任何备份基础架构中。如第 1 篇文章中所述,协议文件对还原镜像必不可少。在调用 storemetadata 时,不再需要向协议文件添加更多的信息;也就是说,可按原样使用它。
还原的用途显而易见:它将快照卷合并到原始卷中;换句话说,在原始卷中,它将每个更改的数据块替换为来自快照的原始数据块。清单 5 显示了该实现:
清单 5. doRestore() 函数代码
142 doRestore() { 143 # 144 # R E S T O R E 145 # 146 # -------------------------------------- 147 148 getSetting "OBJ_ID" 149 id=$_setting 150 # Construct key to search for in currenct protocol file 151 key="RESULT_"$id"_FILE" 152 getSetting $key 153 oldConfig=$_setting 154 155 getSetting "TIMESTAMP" "" $oldConfig 156 timestamp=$_setting 157 for i in `grep "^USER_VOLUME_DATA" $oldConfig | / 158 awk -F= '{print $2}'` 159 do 160 vol=$i"_snap_"$timestamp 161 echo "# Unmounting volume $vol" 162 sudo umount -f $i 163 echo "# Merging volume $vol" 164 sudo lvconvert --merge --background $vol 165 if [ $? -neq 0 ] 166 then 167 echo "# Deactivating volume $vol" 168 sudo lvchange -an $i 169 echo "# Activating volume $vol" 170 sudo lvchange -ay $i 171 fi 172 echo "# Mounting volume $vol" 173 sudo mount $i 174 echo "# Take the backup of volume $vol again" 175 sudo lvcreate -s -n $vol -l100%ORIGIN $i 176 done 177 # if logs included 178 getSetting "ACTION" 179 readAction=$_setting 180 if [ $readAction = "DB2ACS_ACTION_READ_BY_OBJECT" ] 181 then 182 for i in `grep "^USER_VOLUME_LOG" $oldConfig | / 183 awk -F= '{print $2}'` 184 do 185 vol=$i"_snap_"${timestamp} 186 echo "# Umounting volume $vol" 187 sudo umount -f $i 188 echo "# Merging volume $vol" 189 sudo lvconvert --merge --background $vol 190 if [ $? -neq 0 ] 191 then 192 echo "# Deactivating volume $vol" 193 sudo lvchange -an $i 194 echo "# Activating volume $vol" 195 sudo lvchange -ay $i 196 fi 197 echo "# Mounting volume $vol" 198 sudo mount $i 199 echo "# Take the backup of volume $vol again" 200 sudo lvcreate -s -n $vol -l100%ORIGIN $i 201 done 202 fi 203 # -------------------------------------- 204 }
在还原期间,打开了两个协议文件:已更改的当前还原操作的协议文件,以及以只读方式打开的快照备份操作的协议文件。第二个协议文件必须先打开。为此,将会从还原协议文件中读取对象 ID(第 148 和 149 行),生成选项名称(第 151 行),然后读取备份协议文件的名称(第 152 和 153 行)。现在,从协议文件还原并执行相应的镜像,如下所示:
按以下方式处理逻辑卷:
删除 动作(如清单 6 所示)运行以下步骤从相应的卷组中删除快照卷:
清单 6. doDelete() 函数代码
206 doDelete() { 207 # 208 # D E L E T E 209 # 210 # -------------------------------------- 211 getSetting "RESULT_"${objectId}"_FILE" 212 oldConfig=$_setting 213 getSetting "TIMESTAMP" "" $oldConfig 214 timestamp=$_setting 215 for i in `grep "^USER_VOLUME_DATA" $oldConfig | / 216 awk -F= '{print $2}'` 217 do 218 vol=$i"_snap_"${timestamp} 219 echo "# Volume $vol" 220 echo "# "`sudo lvremove -f $vol` 221 done 222 getSetting "DB2BACKUP_LOGS" "" $oldConfig 223 includeLogs=$_setting 224 if [ $includeLogs = "INCLUDE" ] 225 then 226 for i in `grep "^USER_VOLUME_LOG" $oldConfig | / 227 awk -F= '{print $2}'` 228 do 229 vol=$i"_snap_"${timestamp} 230 echo "# Volume $vol" 231 echo "# "`sudo lvremove -f $vol` 232 done 233 fi 235 # -------------------------------------- 236 }
回页首
本文演示了如何使用 LVM 来创建 DB2 数据库的快照镜像。文中详细解释了所有操作的所有动作。您应该很容易看出,使用脚本化接口实现客户脚本非常简单。
回页首
描述 | 名字 | 大小 |
---|---|---|
脚本下载 | dm-1310acs_lvm.sh | --- |