最有效地使用 DB2 HADR 备用数据库

使用 reads on standby 功能

DB2® 高可用性灾难恢复 (High Availability Disaster Recovery, HADR) 是 IBM® DB2 for Linux®, UNIX®, and Windows® 的一种易于使用的数据复制功能,它为部分和全面的站点故障提供了一种高可用性 (HA) 解决方案。从 DB2 V9.7 Fix Pack 1 开始,备用数据库支持来自用户应用程序的读取访问。本文介绍如何将此功能用于读取应用程序,以及目前存在哪些限制。此外,本文还将提供有关如何挖掘备用数据库潜力的建议。

Samir Katti, 软件测试专家, IBM

作者照片Samir Katti 最近 3 年半一直担任 DB2 关系数据库的功能验证工程师。他是该团队一名活跃的成员,负责验证 HADR - reads on standby 功能。他拥有俄勒冈州立大学计算机科学专业的硕士学位。



徐晶, 软件工程师, IBM

徐晶,IBM 中国开发实验室软件工程师,于 2007 年加入 IBM CDL BI 部门,从事 HADR RoS 的测试工作;现在参与 DB2 新功能的开发工作。



2012 年 8 月 27 日

免费下载:IBM® DB2® Express-C 10.1 免费版 或者 DB2® 10.1 for Linux®, UNIX®, and Windows® 试用版
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

简介和背景

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。

  1. 设置 HADR 对后,检查 DB2_HADR_ROS 是否已设置。
    db2 => !db2set
  2. 连接备用数据库应该会得到 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".
  3. 设置 DB2_HADR_ROS 变量,如清单 2 中所示。
    清单 2. 设置变量
    db2 => !db2set DB2_HADR_ROS=ON
    db2 => !db2set
    DB2_HADR_ROS=ON
  4. 停止并重新启动服务器,以使该注册表变量生效,如清单 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.
  5. 激活并连接备用数据库,如清单 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。

  1. 在主要服务器端,执行一些更改,比如创建一个表或插入值,如清单 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.
  2. 在备用服务器端,运行 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。

  1. 在主要服务器端,对数据库执行一些更改,如清单 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.
  2. 在启用 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 命令来获得。

执行以下步骤。

  1. 设置 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
  2. 检查备用数据库上的仅重放窗口是活动还是非活动状态,如清单 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%
  3. 发出一个包含主要数据库上的 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.
  4. 检查仅重放窗口是否处活动状态,如清单 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%
  5. 查看现有应用程序是否已强制关闭,如清单 13 中所示。
    清单 13. 现有应用程序
    db2 => list applications
    SQL1611W  No data was returned by Database System Monitor.
  6. 检查新连接是否被阻止,如清单 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,请确保执行了以下操作。

  • 计划让生成仅重放窗口的所有操作在较短时间内集中发生在主要服务器上。
  • 在主要服务器上启用自动提交,使仅重放窗口保持尽可能短。
  • 关闭主要和备用服务器上的自动维护功能,如清单 15 中所示。
    清单 15. 关闭主要和备用数据库上的自动维护功能
    => db2 UPDATE DATABASE CFG FOR hadrdb USING AUTO_MAINT OFF AUTO_RUNSTATS OFF 
           AUTO_REORG OFF 
    DB20000I  The UPDATE DATABASE CONFIGURATION command completed successfully.

有关 DDL 语句和维护操作的完整列表,请参阅本文 参考资料 一节中的有关 DB2 信息中心的链接,以了解更多相关信息。


将包绑定到备用数据库

通常,包含嵌入式 SQL 的应用程序需要使用 DB2 API 预先编译为主机语言的源文件,然后绑定到相应的数据库。可以使用 db2 CLP 命令 PREP 来预先编译嵌入式 SQL 应用程序。默认情况下,该包将在预编译时自动创建。您也可以在 PREP 命令中随意指定 BINDFILE 选项,以便生成一个绑定文件 (.bnd),在预编译之后,可使用 BIND 实用程序在数据库中使用该绑定文件为此应用程序创建一个包。当一个嵌入式 SQL 应用程序访问的表结构或统计信息更改时,应用程序需要显式或隐式地重新绑定。

执行以下步骤来进行预编译和绑定。

  1. 运行带 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.
  2. 使用 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 内联,使它们可以在备用数据库上访问。

我们希望在阅读本文后,您可更有效和轻松地利用 RoS 功能。

参考资料

学习

获得产品和技术

讨论

条评论

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=831927
ArticleTitle=最有效地使用 DB2 HADR 备用数据库
publish-date=08272012