使用 reads on standby 功能
DB2® 高可用性灾难恢复 (High Availability Disaster Recovery, HADR) 是 IBM®
DB2 for Linux®, UNIX®, and Windows® 的一种易于使用的数据复制功能,它为部分和全面的站点故障提供了一种高可用性
(HA) 解决方案。从 DB2 V9.7 Fix Pack 1
开始,备用数据库支持来自用户应用程序的读取访问。本文介绍如何将此功能用于读取应用程序,以及目前存在哪些限制。此外,本文还将提供有关如何挖掘备用数
据库潜力的建议。
简介和背景
DB2 for Linux, UNIX,
and Windows 高可用性灾难恢复 (High Availability Disaster Recovery, HADR)
功能是一种数据复制功能,它为部分和全面的站点故障提供了一种高可用性解决方案。HADR
通过将称为主要数据库的源数据库中的数据更改复制到称为备用数据库的目标数据库,防止数据丢失。
HADR 是在 DB2 V8.2 中引入的。在 DB2 V9.7 Fix Pack 1 之前,备用服务器只能前滚从主要服务器传来的日志记录,并且对用户而言是离线的。不允许在备用数据库上建立用户连接。
从
DB2 V9.7 Fix Pack 1 开始,reads on standby 功能 (HADR RoS)
支持只读应用程序访问备用数据库。这只有在启用了 reads on standby 功能时才可行。使用此功能,读/写应用程序可访问 HADR
主要数据库,只读应用程序可访问主要或备用数据库。这支持您将在主要数据库上运行的一些只读工作负载卸载到备用数据库上。连接备用数据库的应用程序在故障
转移时不会影响备用数据库的可用性。
本文介绍如何为在备用数据库上的读取操作设置 reads on standby 功能,探讨从当前备用数据库读取数据的限制。此外,它还提供了有关挖掘备用数据库潜力的建议。本文假设读者熟悉 HADR 对的设置。
设置 reads on standby使用 reads on standby 功能,一个 HADR 对的备用数据库可用于支持只读应用程序。备用数据库可通过设置注册表变量 DB2_HADR_ROS 的值来启用读取模式。该注册表变量可设置为 ON
来启用 reads on
standby。该注册表变量的设置不是动态的。换句话说,备用服务器必须停止并重新启动,对该注册表变量的更改才会生效。如果由于一个接管操作而使备用
服务器成为主要服务器,那么该注册表变量对于新的主要服务器没有任何影响。读取功能支持 HADR 同步模式:ASYNC、NEARSYNC、SYNC 和
SUPERASYNC。在备用服务器处于本地保持 (local catch-up) 时不支持读取功能。
执行以下步骤来设置 DB2_HADR_ROS。
- 设置 HADR 对后,检查 DB2_HADR_ROS 是否已设置。
db2 => !db2set - 连接备用数据库应该会得到 SQL1776 rc=1,如清单 1 中所示。
清单 1. 连接备用数据库
db2 => connect to hadrdb
SQL1776N The command is not supported on an HADR standby database or on an
HADR standby database with the current configuration or state. Reason code =
"1".
- 设置 DB2_HADR_ROS 变量,如清单 2 中所示。
清单 2. 设置变量
db2 => !db2set DB2_HADR_ROS=ON
db2 => !db2set
DB2_HADR_ROS=ON
- 停止并重新启动服务器,以使该注册表变量生效,如清单 3 中所示。
清单 3. 停止并重新启动服务器
db2 => deactivate db hadrdb
DB20000I The DEACTIVATE DATABASE command completed successfully. db2 => !db2stop
SQL1064N DB2STOP processing was successful.
db2 => !db2start
SQL1063N DB2START processing was successful.
- 激活并连接备用数据库,如清单 4 中所示。
清单 4. 激活并连接
db2 => activate db hadrdb
DB20000I The ACTIVATE DATABASE command completed successfully. db2 => connect to hadrdb
Database Connection Information
Database server = DB2/LINUXX8664 9.7.5
SQL authorization ID = KATTI
Local database alias = HADRDB
使用 RoS 验证 HADR 设置
用
户通常想验证 HADR 设置是否像预期一样工作,以及在配置 HARD 对之后是否没有丢失数据。在 DB2 V9.7 FP1 之前,您必须使用
TAKEOVER 让备用服务器变成新的主要服务器,才能验证 HADR
设置。不允许在备用服务器上建立任何连接,因为它对用户而言是离线的。因此,很难连接备用服务器上的数据。让备用服务器上线的惟一方式是
TAKEOVER。
在 RoS 可用之前,需要执行下面的过程来验证 HADR。
- 在主要服务器端,执行一些更改,比如创建一个表或插入值,如清单 5 中所示。
清单 5. 更改主要服务器
[1049] [xjcd@db2eng63] /home/xjcd
=> db2 connect to hadrdb
Database Connection Information Database server = DB2/LINUXX8664 9.7.5
SQL authorization ID = XJCD
Local database alias = HADRDB
[1050] [xjcd@db2eng63] /home/xjcd
=> db2 "create table t1(c1 int)"
DB20000I The SQL command completed successfully.
[1051] [xjcd@db2eng63] /home/xjcd
=> db2 "insert into t1 values(123)"
DB20000I The SQL command completed successfully.
[1052] [xjcd@db2eng63] /home/xjcd
=> db2 connect reset
DB20000I The SQL command completed successfully.
- 在备用服务器端,运行 TAKEOVER HADR 并检查在主要服务器上执行的更改,如清单 6 中所示。
清单 6. 检查备用服务器上的更改
[898] [xjcd@db2eng64] /home/xjcd
=> db2 takeover hadr on db hadrdb
DB20000I The TAKEOVER HADR ON DATABASE command completed successfully.
[899] [xjcd@db2eng64] /home/xjcd
=> db2 connect to hadrdb
Database Connection Information
Database server = DB2/LINUXX8664 9.7.5
SQL authorization ID = XJCD
Local database alias = HADRDB
[900] [xjcd@db2eng64] /home/xjcd
=> db2 "select * from t1"
C1
-----------
123
1 record(s) selected.
在 DB2 V97 FP1 及以后的版本中启用了 read on standby 之后,验证 HADR 设置变得非常简单。可直接建立与备用服务器的连接,无需接管操作。
执行以下步骤来使用 RoS 验证 HADR。
- 在主要服务器端,对数据库执行一些更改,如清单 7 中所示。
清单 7. 更改主要数据库
[1049] [xjcd@db2eng63] /home/xjcd
=> db2 connect to hadrdb
Database Connection Information
Database server = DB2/LINUXX8664 9.7.5
SQL authorization ID = XJCD
Local database alias = HADRDB
[1050] [xjcd@db2eng63] /home/xjcd
=> db2 "create table t1(c1 int)"
DB20000I The SQL command completed successfully.
[1051] [xjcd@db2eng63] /home/xjcd
=> db2 "insert into t1 values(123)"
DB20000I The SQL command completed successfully.
[1052] [xjcd@db2eng63] /home/xjcd
=> db2 connect reset
DB20000I The SQL command completed successfully.
- 在启用 RoS 后直接连接备用服务器,检查在主要数据库上执行的更改,如清单 8 中所示。
清单 8. 在备用数据库上检查更改
[910] [xjcd@db2eng64] /home/xjcd
=> db2 connect to hadrdb
Database Connection Information
Database server = DB2/LINUXX8664 9.7.5
SQL authorization ID = XJCD
Local database alias = HADRDB
[911] [xjcd@db2eng64] /home/xjcd
=> db2 "select * from t1"
C1
-----------
123
1 record(s) selected.
在备用数据库上的仅重放窗口当
一个 HADR 活动备用数据库重放 DDL
日志或维护操作时,备用服务器进入仅重放窗口。当备用服务器处于仅重放窗口时,与备用服务器的现有连接将终止,并阻止与备用服务器建立新连接
(SQL1776N Reason Code 4)。在发出 DDL
或维护操作的所有事务都完成后,即可在备用服务器上建立新连接。在仅重放窗口开始时,会强制关闭现有应用程序并返回一个错误
(SQL1224N)。仅重放窗口状态可通过在备用数据库上执行 db2pd -db db_name -hadr 命令来获得。
执行以下步骤。
- 设置 HADR 对并建立一个与备用数据库的连接,然后发出以下命令(如清单 9 中所示)来获取备用数据库上当前活动的应用程序。
清单 9. 获取备用数据库上的应用程序状态
db2 => list applications
Auth Id Application Appl. Application Id DB # of
Name Handle Name Agents
-------- -------------- ---------- -------------- -------- -----
KATTI db2bp 13 *LOCAL.katti.120305194800 HADRDB 1
- 检查备用数据库上的仅重放窗口是活动还是非活动状态,如清单 10 中所示。
清单 10. 检查仅重放窗口
db2 => !db2pd -db hadrdb -hadr
Database Partition 0 -- Database HADRDB -- Active Standby -- Up 0 days 00:05:37 –
Date 03/05/2012 11:50:58
HADR Information:
Role State SyncMode HeartBeatsMissed LogGapRunAvg (bytes)
Standby Peer Sync 0 3298
ConnectStatus ConnectTime Timeout
Connected Mon Mar 5 11:45:26 2012 (1330976726) 120
ReplayOnlyWindowStatus ReplayOnlyWindowStartTime MaintenanceTxCount
Inactive N/A 0
LocalHost LocalService
grebe DB2_katti
RemoteHost RemoteService RemoteInstance
petrel xkatti katti
PrimaryFile PrimaryPg PrimaryLSN
S0000001.LOG 13 0x000000000235DFB6
StandByFile StandByPg StandByLSN StandByRcvBufUsed
S0000001.LOG 13 0x000000000235DFB6 0%
- 发出一个包含主要数据库上的 DLL 的未提交事务,如清单 11 中所示。
清单 11. 发出一个未提交事务
db2 => update command options using c off
DB20000I The UPDATE COMMAND OPTIONS command completed successfully.
db2 => create table t1(c1 int, c2 int)
DB20000I The SQL command completed successfully.
- 检查仅重放窗口是否处活动状态,如清单 12 中所示。
清单 12. 检查仅重放窗口
db2 => !db2pd -db hadrdb -hadr
Database Partition 0 -- Database HADRDB -- Active Standby -- Up 0 days 00:10:26
-- Date 03/05/2012 11:55:47
HADR Information:
Role State SyncMode HeartBeatsMissed LogGapRunAvg (bytes)
Standby Peer Sync 0 1441
ConnectStatus ConnectTime Timeout
Connected Mon Mar 5 11:45:26 2012 (1330976726) 120
ReplayOnlyWindowStatus ReplayOnlyWindowStartTime MaintenanceTxCount
Active Mon Mar 5 11:54:09 2012 (1330977249) 1
LocalHost LocalService
grebe DB2_katti
RemoteHost RemoteService RemoteInstance
petrel xkatti katti
PrimaryFile PrimaryPg PrimaryLSN
S0000001.LOG 15 0x000000000235FCFC
StandByFile StandByPg StandByLSN StandByRcvBufUsed
S0000001.LOG 14 0x000000000235EE8A 0%
- 查看现有应用程序是否已强制关闭,如清单 13 中所示。
清单 13. 现有应用程序
db2 => list applications
SQL1611W No data was returned by Database System Monitor.
- 检查新连接是否被阻止,如清单 14 中所示。
清单 14. 新连接
db2 => connect to hadrdb
SQL1776N The command is not supported on an HADR standby database or on an
HADR standby database with the current configuration or state. Reason code =
"4".
所以,重放窗口显然对备用数据库上的用户业务具有影响。如果在备用数据库上启用了 RoS,请确保执行了以下操作。
将包绑定到备用数据库通
常,包含嵌入式 SQL 的应用程序需要使用 DB2 API 预先编译为主机语言的源文件,然后绑定到相应的数据库。可以使用 db2 CLP 命令
PREP 来预先编译嵌入式 SQL 应用程序。默认情况下,该包将在预编译时自动创建。您也可以在 PREP 命令中随意指定 BINDFILE
选项,以便生成一个绑定文件 (.bnd),在预编译之后,可使用 BIND 实用程序在数据库中使用该绑定文件为此应用程序创建一个包。当一个嵌入式
SQL 应用程序访问的表结构或统计信息更改时,应用程序需要显式或隐式地重新绑定。
执行以下步骤来进行预编译和绑定。
- 运行带 BINDFILE 选项的 PREP 命令来生成一个绑定文件 (sample.bnd),如清单 16 中所示。
清单 16. 带 BINDFILE 选项的 PREP 命令
=> db2 prep sample.sqc bindfile
LINE MESSAGES FOR sample.sqc
------ --------------------------------------------------------------------
SQL0060W The "C" precompiler is in progress.
SQL0091W Precompilation or binding was ended with "0"
errors and "0" warnings.
- 使用 BIND 实用程序在数据库中创建该包,如清单 17 中所示。
清单 17. 使用 BIND 实用程序
=> db2 bind sample.bnd
LINE MESSAGES FOR sample.bnd
------ --------------------------------------------------------------------
SQL0061W The binder is in progress.
SQL0091N Binding was ended with "0" errors and "0" warnings.
请注意,预编译和绑定都需要您连接至该数据库。
前面已经讨论过,不允许在 HADR 备用数据库上执行任何写入操作。因此,不允许在备用数据库上执行绑定和重新绑定,因为它们将向数据库写入数据。当尝试将一个包绑定到备用数据库时,将报告错误 SQL1773N 和原因代码 5,如清单 18 中所示。
清单 18. 在备用服务器上执行绑定时出现的错误
=> db2 bind sample.bnd
LINE MESSAGES FOR sample.bnd
------ --------------------------------------------------------------------
SQL0061W The binder is in progress.
SQL1773N The statement or command requires functionality
that is not supported on a read-enabled HADR standby
database. Reason code = "5".
SQL0082C An error has occurred which has terminated
processing.
SQL0092N No package was created because of previous errors.
SQL0091N Binding was ended with "3" errors and "0" warnings.
当需要在备用数据库上绑定或重新绑定包时,必须在主要数据库上执行绑定/重新绑定。绑定/重新绑定操作会传输到备用服务器上进行重放,因为将会有为它们编写的日志记录。
绑定/重新绑定之后,可以将应用程序的可执行二进制文件复制到备用数据库所在的服务器上,然后运行该应用程序。但是,请注意绑定和重新绑定命令。它们将触发备用服务器上的仅重放窗口。
备用服务器上的隔离级别备
用数据库上的读取程序只能在 Uncommitted Reads (UR) 隔离级别上运行。此限制的原因在于,DB2 HADR
基于日志传输。正如您所知道,主要服务器上的事务将生成日志记录,这些日志记录将传输到备用数据库上。备用数据库重新执行这些日志记录,就像在还原数据库
后前滚一样,以确保与主要数据库的数据一致性。但是,比 UR
更高的隔离级别所需的锁不会传输到备用数据库,读取程序在重放日志记录时不会获取任何锁。简言之,备用数据库上的数据不受任何锁保护,所以备用数据库上的
应用程序只能在 UR 隔离级别下读取。
清单 19. 在比 UR 更高的隔离级别上读取时的错误
=> db2 "select * from t1 with RR"
C1
-----------
SQL1773N The statement or command requires functionality that is not
supported on a read-enabled HADR standby database. Reason code = "1".
如果一些现有的只读应用程序是在比 UR 更高的隔离级别上实现的,并且您不希望由于此隔离级别错误而被破坏,可以通过设置 DB2_STANDBY_ISO 注册表变量,强制它们在 UR 隔离级别静默地运行,如清单 20 中所示。
清单 20.
在比 UR 更高的隔离级别上进行读取时发生的错误
=> db2set DB2_STANDBY_ISO=UR
# We need to restart DB2 instance here so that this registry variable take effect
=> db2 connect to testdb
Database
Connection Information
Database server = DB2/LINUXX8664 9.7.5
SQL authorization ID = XJCD
Local database alias = TESTDB
=> db2 "select * from t1 with RR"
C1
-----------
1
2
3
3 record(s) selected.
对于需要比 UR 更高的隔离级别的只读应用程序,只能在主要数据库上运行它们。
备用数据库上的统计信息SQL 优化器在生成访问计划时需要数据库对象的统计信息。如果没有生成统计信息,优化器可能选择一个成本不是最低的访问计划,查询性能将受到影响。
RUNSTATS
实用程序用于收集 DB2 中的统计信息。它将在指定的对象(表或索引)上抽样,并计算统计信息,然后将结果写入具有 SYSSTAT
模式的系统目录表中。因为 HADR 备用数据库上不支持写入操作,所以备用数据库上也不支持 RUNSTATS 实用程序。
如果希望更新备用数据库上的统计信息,以改善备用数据库上的应用程序的查询性能,可采用以下替代方式。
- 在主要数据库上执行 RUNSTATS。不错,最基本且最简单的方式是在主要数据库上运行 RUNSTATS。因为 RUNSTATS 会将结果写入系统目录表,所以将生成相应的日志记录,并且它们将传输到备用数据库并重放。因此,备用数据库上的统计信息将更新。
- 直接手动更新统计信息目录表。但是,很明显第一个解决方案中的 RUNSTATS 对主要数据库的性能有一定的影响。统计信息目录表中的一些字段可以更新,所以您可以根据需要来手动更新统计信息。但是,更新目录表有一定的风险,所以如果采用此解决方案,请特别小心。
- 使
用优化器配置文件来向优化器指定一个计划。不过,可能主要数据库和备用数据库上的一些条件不同,即使不推荐这么做。例如,主要数据库上的一个表空间具有比
备用数据库性能更高的容器,主要数据库上的统计信息不适用于备用数据库。在此情况下,您必须为同一个查询在主要和备用数据库上制定不同的访问计划。
您可以在内联指南或优化配置文件中指定查询的优化指南。通常是将优化配置文件(XML
文件)插入到 SYSTOOLS.OPT_PROFILE 表中,然后在查询之前启用这些配置文件。DB2
优化器将依据优化配置文件生成并选择一个访问计划。有关使用优化配置文件的更多细节,请参阅 参考资料 一节中 “DB2 9 中的查询优化新特性” 文章,了解更多信息。
因
为写入操作在备用数据库上是禁止的,所以无法将优化配置文件插入到备用数据库上的 SYSTOOLS.OPT_PROFILE
中。替代方法是插入到主要数据库上的配置文件中,然后将相应的日志记录传输到备用数据库。重放这些日志记录后,优化配置文件将位于备用数据库中,以供使
用。
在备用服务器上处理 LOB在
V9.7 Fix Pack 5 之前,不允许在备用数据库上读取大对象 (LOB),比如 BLOB、CLOB 或 DBCLOB。在 DB2
V9.7 之前,所有 LOB 都存储在一个与其他非 LOB 列分开的表空间中。当尝试读取一个 LOB 时,您将获得返回代码 SQL1773N
和原因代码 1,如清单 21 中所示。
清单 21. 非内联 LOB 在备用数据库上是禁止的
=> db2 "select C2 from T"
C2
-----------------------
SQL1773N The statement or command requires functionality that is not
supported on a read-enabled HADR standby database. Reason code = "1".
在
DB2 V9.7 中,引入了内联 LOB。这些 LOB 存储在与非 LOB 列相同的表空间中。在 V9.7 Fix Pack 5
及更高版本中,备用数据库支持内联 LOB。所以,对于小型 LOB,应该尽可能让它们内联。要检查一行中的 LOB 列是否是内联,可使用
ADMIN_IS_INLINED 表函数,如清单 22 中所示。
清单 22. 检查一个 LOB 列是否是内联的
=> db2 "select ADMIN_IS_INLINED(c1) from t2"
1
------
1
1 record(s) selected.
查询结果 1 表示此行的此列是内联的,0 表示它不是内联的。
结束语
从
DB2 V9.7 Fix Pack 1 开始,DB2 提供了 reads on standby 功能和 HADR
功能。您可以将只读应用程序放在备用数据库上。此功能可帮助您平衡主要服务器上的工作负载。由于日志传输和重放机制,备用数据库上的只读应用程序存在一些
限制。本文介绍了这些限制,展示了如何让备用数据库上的应用程序有效地运行,包括以下方法。
- 设置注册表变量 DB2_HADR_ROS=on 来启用 RoS 功能。
- 让主要服务器上包含 DDL 语句的事务保持尽可能短,以减少仅重放窗对备用服务器的影响。
- 将包绑定在主要服务器上,并在备用服务器上运行相应的应用程序。
- 为备用服务器上的应用程序使用 Uncommitted Read (UR) 隔离级别。
- 尽可能保持 LOB 内联,使它们可以在备用数据库上访问。
添加新评论0 条评论