DB2 HADR 性能调优及 HADR 模拟器

2 篇文章 0 订阅

HADR 是 DB2 中一种高可用性和灾难恢复的解决方案。由于 HADR 需要使用网络将日志进行传输,并且考虑到各种其它的因素,所以用户在使用中可能会造成主机性能下降。本文介绍了 HADR 各个参数对性能的影响,并且讲解了通过监控对这些参数进行调整。本文还介绍了 HADR 模拟器,通过举例说明了 HADR 模拟器的使用。并且描述了如何使用该工具确定 HADR 的最优配置。


DB2 HADR 性能简述

HADR(高可用性灾难恢复)是 DB2 的一个组件,它可以给用户提供一种高可用性和灾备的方案。关于这个组件的介绍及配置,请参看 DB2 信息中心和 HADR 最佳实践。DB2 HADR 的基本原理是主机使用 TCP/IP 协议通过网络将日志发送到备机,备机随后将这些日志进行重做,以保证和主机的一致。请参考 http://www.ibm.com/developerworks/ cn/data/library/techarticles/dm-1010baosf/。那么,性能问题从何而来呢? DB2 HADR 传送日志的方式有三种,也就是 HADR 的三种同步方式:同步,近同步和异步。这三种方式在以上参考资料中有详细的介绍和分析。基本上,HADR 的性能问题主要源于两个方面:

一.备机对日志的重做操作比较慢,导致备机上接收日志的缓冲区装满,主机无法将日志发送至备机。这种情况下,我们通过 db2pd 可以观测到如下结果(请注意 StandByRcvBufUsed 为 100%):

 Database Partition 0 -- Database HADRDB -- Active Standby 
 -- Up 0 days 03:06:17 -- Date 02/13/2011 22:18:24 

 HADR Information: 
 Role    State                SyncMode HeartBeatsMissed   LogGapRunAvg (bytes) 
 Standby Peer                 Nearsync 0                  6029610 

 ConnectStatus ConnectTime                           Timeout 
 Connected     Sun Feb 13 22:17:38 2011 (1297664258) 120 

 PeerWindowEnd                         PeerWindow 
 Sun Feb 13 22:18:33 2011 (1297664313) 10 

 ReplayOnlyWindowStatus ReplayOnlyWindowStartTime             MaintenanceTxCount 
 Inactive               N/A                                   0 

 LocalHost                                LocalService 
 grebe                                    54321 

 RemoteHost                               RemoteService      RemoteInstance 
 petrel                                   54321              sfbao 

 PrimaryFile  PrimaryPg  PrimaryLSN 
 S0002484.LOG 2          0x00000000049FA6EE 

 StandByFile  StandByPg  StandByLSN         StandByRcvBufUsed 
 S0002484.LOG 2          0x00000000049FA6EE 100%

二.网络传输日志不够快,可能是带宽不够,也可是因为网络不稳定,或者是其它原因,导致网络频繁出于阻塞状态。从而主机上的日志不能快速的传送到备机。这种情况下,我们会从格式化以后的 db2trc 里面看到以下片段:

 13 0.339990000   hdrEduAcceptEvent entry [eduid 116 eduname db2hadrp] 
 14 0.372926000   | hdrSendMsg entry [eduid 116 eduname db2hadrp] 
 15 0.372927000   | | hdrSendBuffer entry [eduid 116 eduname db2hadrp] 
 16 0.373004000   | | hdrSendBuffer exit [rc = 0x810F001F = -2129723361 
 = SQLO_SOCKET_NOT_READY] 
 
 17 0.373004000   | hdrSendMsg exit [rc = 0x810F001F = -2129723361 
= SQLO_SOCKET_NOT_READY] 

 18 0.373006000   hdrEduAcceptEvent exit

以下,我们将会对各个情况进行分析并对这些情况进行调优。

DB2 HADR 相关性能参数

DB2_HADR_BUF_SIZE:该参数代表 HADR 备机上接收日志的缓冲区的大小。这些日志可能写到了磁盘上,也可能没有。这些日志还没有被重做。

DB2_HADR_PEER_WAIT_LIMIT:该值表示 HADR 在这段时间内没有收到备机的任何响应,就会主动断开连接。断开连接以后,如果主机设置了 HADR_PEER_WINDOW,主机上会转到 disconnect peer 状态,主机的事务被挂起直到 PEER 窗口消失;如果主机没有设置 HADR_PEER_WINDOW,主机上的事务会马上继续。

DB2_HADR_SOSNDBUF:这个值表示 HADR 线程在 TCP 这层的发送窗口的大小。默认情况下是操作系统内核设置的 TCP 发送的窗口大小。对于 LINUX,对应 net.ipv4.tcp_wmem。最大不能超过内核允许的最大值。

DB2_HADR_SORCVBUF:该值表示 HADR 线程在 TCP 层的接收窗口的大小。默认大小事操作系统内核默认的 TCP 接收窗口的大小。对于 LINUX,对应 net.ipv4.tcp_rmem。最大值不能超过操作系统内核允许的最大值。

HADR_SYNCMODE:该参数表示 HADR 的同步模式。关于三种模式的详细解释请参考:DB2 HADR 监控详解 一文。

HADR_PEER_WINDOW:请参考 DB2 HADR 监控详解 一文。

DB2 还有一些和前滚性能有关的参数,例如 redo 线程的数量,可以联系 IBM 获得技术支持。DB2 中,前滚的过程是多个线程并行完成的。日志记录存放在队列中,负责前滚的线程并行的去队列中取出日志记录进行重做。理论上说,线程数量多则可增加并发度,但是也会增加线程等待的开销。所以,合适的值非常重要。

DB2 HADR 性能简述

以下,我们对各种情况下的性能问题进行分析和调优。

备机重做效率低

如果备机和主机的硬件性能相当,但是仍然发现备机上的接收缓冲区被填满。可以对 rollforward 中的 queue,queue set 和 agent 的数量进行调整。DB2 中的 rollforward 是一个并行模型。日志被放入 queue 里面,然后 agent 再去 queue 中取。默认情况下,agent 的数量和 CPU 的数量相等。然而在实际工作中,过多的 agent 反倒增加了 agent 之间同步和通信的开销,使得重做的效率下降。而过多的 queue 和 queueset 也会增加 agent 查找日志记录的时间,降低重做效率。所以,适当的 queue,queue set 和 agent 的数量很重要。不幸的是,笔者没有一个有效的公式计算出最优的值,只能靠尝试获合适的值。注意,请在 IBM 工程师指导下试用一下参数。

设置这三个参数的过程如下所示。

首先将三个参数写入一个文件中,如 bpvar.cfg:

PREC_NUM_AGENTS=4

PREC_NUM_QSETSIZE=8

PREC_NUM_QSETS=4

然后设置 DB2BPVARS:

 db2set DB2BPVARS= <path of bpvar.cfg>

这项设置需要重新启动实例,重启以后,可以从 db2diag.log 中观察到修改以后的变化:

 2011-01-27-01.51.09.919359-480 I102358E492         LEVEL: Warning 
 PID     : 5131                 TID  : 47596378777920PROC : db2sysc 
 INSTANCE: sfbao                NODE : 000          DB   : HADRDB 
 APPHDL  : 0-7                  APPID: *LOCAL.sfbao.110127095104 
 AUTHID  : SFBAO 
 EDUID   : 16                   EDUNAME: db2agent (HADRDB) 
 FUNCTION: DB2 UDB, recovery manager, sqlprecm, probe:2000 
 DATA #1 : <preformatted> 
 Using parallel recovery with 4 agents 4QSets 8 queues and 16 chunks

网络的带宽

在选择 HADR 作为灾备方案前,一定要论证可行性。其实对于任何一种灾备方案,对网络的基本要求就是带宽要大于所要传输的数据的要求。DB2 HADR 的主机和备机之间传输的数据库的日志,一般来说优于文件系统同步。但是仍然要求带宽要大于日志产生的速度。

可以通过以下方法计算日志产生的速度。

1. 如果主机已经以强制的方式启动为 HADR 主机(备机并没有启动),在一定时间间隔内,执行 db2pd -db dbname -hadr。可以从主机上两次 LSN 的差值上计算出一共产生了多少日志。例如:

第一次:

 HADR Information: 
 Role    State                SyncMode HeartBeatsMissed   LogGapRunAvg (bytes) 
 Primary Disconnected         Nearsync 0                  27735               

 ConnectStatus ConnectTime                           Timeout   
 Disconnected  Mon Feb 14 00:38:18 2011 (1297672698) 120       

 PeerWindowEnd                         PeerWindow 
 Mon Feb 14 00:38:28 2011 (1297672708) 10        

 LocalHost                                LocalService      
 petrel                                   54321             

 RemoteHost                               RemoteService      RemoteInstance    
 grebe                                    54321              sfbao             

 PrimaryFile  PrimaryPg  PrimaryLSN        
 S0006005.LOG 0          0x00000000080FCA43 

 StandByFile  StandByPg  StandByLSN        
 S0006005.LOG 0          0x00000000080FCA43

第二次:

 HADR Information: 
 Role    State                SyncMode HeartBeatsMissed   LogGapRunAvg (bytes) 
 Primary Disconnected         Nearsync 0                  0                   

 ConnectStatus ConnectTime                           Timeout   
 Disconnected  Mon Feb 14 00:38:18 2011 (1297672698) 120       

 PeerWindowEnd                         PeerWindow 
 Mon Feb 14 00:38:28 2011 (1297672708) 10        

 LocalHost                                LocalService      
 petrel                                   54321             

 RemoteHost                               RemoteService      RemoteInstance    
 grebe                                    54321              sfbao             

 PrimaryFile  PrimaryPg  PrimaryLSN        
 S0006006.LOG 0          0x000000000810019D 

 StandByFile  StandByPg  StandByLSN        
 S0006005.LOG 0          0x00000000080FCA43

这段时间内,主机上产生的日志量为:0x000000000810019D - 0x00000000080FCA43 = 375A。用这个数量除以时间就是需要的最小带宽。

2. 如果主机仍然是正常的 DB,则可以通过两次 db2pd -logs -db dbname 粗略计算。例如。

第一次:

 Logs: 
 Current Log Number            0         
 Pages Written                 1         
 Cur Commit Disk Log Reads     0                   
 Cur Commit Total Log Reads    0                   
 Method 1 Archive Status       n/a 
 Method 1 Next Log to Archive  0         
 Method 1 First Failure        n/a 
 Method 2 Archive Status       n/a 
 Method 2 Next Log to Archive  n/a 
 Method 2 First Failure        n/a 
 Log Chain ID                  1         
 Current LSN                   0x000000000274173B

第二次:

 Logs: 
 Current Log Number            2         
 Pages Written                 2         
 Cur Commit Disk Log Reads     0                   
 Cur Commit Total Log Reads    0                   
 Method 1 Archive Status       Success 
 Method 1 Next Log to Archive  1         
 Method 1 First Failure        n/a 
 Method 2 Archive Status       n/a 
 Method 2 Next Log to Archive  n/a 
 Method 2 First Failure        n/a 
 Log Chain ID                  1         
 Current LSN                   0x000000000274A8C0

这段时间内,产生的日志量为:(0x000000000274A8C0 - 0x000000000274173B = 9185)。用这个值除以时间差,就是需要的最小带宽。注意,带宽往往以 bit 为单位,而我们计算的结果是以 BYTE 为单位的。

值得提出的是,如果瓶颈是网络的带宽,压缩网络上的数据对于缓解这种问题效果会很明显。可以采用第三方的工具(软件或者硬件)对网络上的数据进行压缩,例如 SSH 的通道。

当 DB2 启用表压缩以后,产生的日志也会相应压缩,但是笔者并没有对这种情况进行测试,所以不能提供详细的数据。

网络的 RTT 过大

这种情况多发生在异地使用 HADR 做灾备。在这种情况下,虽然带宽很大,但是由于 RTT(round trip time)偏大,日志发送和网络 ACK 需要较长时间,导致 TCP 的发送窗口填满而产生拥塞。

这种情况下,可以试用一下方法对性能进行调优。

设置 TCP 窗口大小

设置较大的 TCP 窗口大小往往会有很明显效果,当然,前提是 HADR 的同步模式为异步或者近同步。

首先修改内核参数 tcp_wmem 和 tcp_rmem。如果这两个参数的最大值适当,则使用以下命令设置:

db2set DB2_HADR_SOSNDBUF=102400
db2set DB2_HADR_SORCVBUF=102400

窗口的大小多少最合适呢? TCP 协议规定,每一次发送窗口的数据,都需要一个对端的一个 ACK。HADR 使用非阻塞 IO 发送日志,因此,最优的情况,应该是当 ACK 返回时,TCP 发送缓冲区中的数据还没有满(或者说刚好满)。也就是在一个 RTT 周期中产生的日志刚好没有填满缓冲区。这样,发送缓冲区中就始终有空间使用。

另外,我们还需要保证备机上的接收缓冲区始终有空间可用。备机一次接收数据的时间,主机可能已经发送了好多次数据,因此,接收缓冲的大小应该能容下这段时间内主机发送过来的所有数据。

一般情况下,这两个参数的值设置的过大不会负面影响。最小值可以用一下公式进行计算:

window size= max((flush size)*(round trip time), ((average time to receiving logs on S)/(average time of sending logs on P)*(flush size)))

请参照这篇文章 http://www.ibm.com/developerworks/wikis/display/data/HADR_sim 并获取 db2flushsize 工具,该工具可以针对日志文件输出 flush size。

设置网卡绑定

网卡绑定可以将多个物理网卡绑定到同一个 IP 地址上。网卡绑定有两种模式,一种是冗余,这种模式下,当一个网卡失效时,其它的可以接管它的功能继续工作;另一种是负载均衡,也就是多个网卡同时工作。这样,可以使用多个网络流增加网络上的流量。

在使用 HADR 做灾备时,如果两地距离较远,RTT(Round Trip Time)较大,但是带宽足够,则可以尝试一下网卡绑定的负载均衡功能。

下面,我们以 Linux 为例,配置一下该功能,笔者环境中,有两块物理网卡 eth0 和 eth1。

首先,到 /etc/sysconfig/network-scirpt/ 目录下,创建 ifcfg-bond0 文件,内容如下:

 DEVICE=bond0 
 ONBOOT=yes 
 BOOTPROTO=static 
 IPADDR=9.123.146.9 
 NETMASK=255.255.255.0 
 BROADCAST=9.123.146.255 
 TYPE=Ethernet

相同目录下,修改 ifcfg-eth0:

 DEVICE=eth0 
 ONBOOT=yes 
 MASTER=bond0 
 BOOTPROTO=none

相同目录下,修改 ifcfg-eth1:

 DEVICE=eth1 
 ONBOOT=yes 
 MASTER=bond0 
 BOOTPROTO=none

修改 /etc/modprobe.conf 文件,添加如下内容:

 alias bond0 bonding 
 options bond0 miimon=100 mode=0

修改 /etc/rc.d/rc.local,添加以下内容:

 ifenslave bond0 eth0 eth1 
 route add default gw 9.123.146.1 – interface bond0

设置巨型帧

对于多数操作系统,默认情况下,TCP/IP 协议中 MTU 的大小是 1500 个字节。当前的网络和以前的比较起来有很大改善,带宽提高很多。所以,可以使能巨型帧,使得 MTU 的大小为 9000 个字节。这样,通过节省每个帧在网络上传输时间来调优网络性能。注意,为了使用巨型帧,网络中的所有中转节点必须支持它。

而在操作系统中设置巨型帧也很简单,只要内核支持,可以通过 ifconfig 或者在配置文件中配置 MTU 即可。

HADR 模拟器

HADR 模拟器是 HADR 开发团队开发的专门模拟 HADR 工作的软件,它的原理和 HADR 工作原理非常接近。通过 HADR 模拟器,用户可以模拟各种条件下 HADR 的性能。根据这些模拟的效果,用户可以选择一个最适合该环境下 HADR 的配置,从而用在真实的 HADR 环境里面。

用户可以通 http://www.ibm.com/developerworks/wikis/display/data/HADR_sim 下载该软件。

关于 HADR 模拟器的参数和输出结果的说明,读者也可以参考以上链接。在这篇文章里,笔者主要就提供一些 HADR 模拟器的使用例子。用户可以根据自己的需要对各个参数进行反复测试,从而取得最优值。

HADR 模拟器仿真实例

获取写日志时的磁盘效率

关于 HADR 如何在各种模式下将日志写入磁盘并且发送到网络上,请参考这篇文档。为了能够更精确的确定各个环境中磁盘的性能,我们最好能够知道我们自己的数据库以多大为单位写磁盘。在 http://www.ibm.com/developerworks/wikis/display/data/HADR_sim 中,作者提供了一个工具 db2flushsize。这个工具能够根据已经存在的日志文件来计算在该日志上有多少次写操作,以及每次写操作的大小。以一下数据库的日志为例:

 sfbao@petrel:~>./db2flushsize S0000201.LOG 

 File S0000201.LOG 
 Page 1: 4080 bytes of data, flag 0x0000 
 Page 2: 4080 bytes of data, flag 0x0010, end of flush, flush size 2 
 Page 3: 4080 bytes of data, flag 0x0000 
 Page 4: 4080 bytes of data, flag 0x0010, end of flush, flush size 2 

 Total 2 flushes. Average flush size 2.0 pages

从这个日志中,我们可以看出来写操作的平均大小是 2 个页。我们也可以使用更多的日志文件来计算更精确的平均值。

知道了这个值,也就是模拟器中使用的 -flushsize,我们就可以使用它来计算日志所在位置的磁盘的效率。

 sfbao@petrel:~>./simhadr.Linux -t 5 -testDisk /u/sfbao/ -flushsize 2 
 + simhadr -t 5 -testDisk /u/sfbao/ -flushsize 2 

 Measured sleep overhead: 0.003972 second, using spin time 0.004766 second. 

 Writing to file /u/sfbao//simhadr.tmp 
 Press Ctrl-C to stop. 

 Total 2081 writes in 5.001168 seconds, 0.002403 sec/write, 2 pages/write 

 Total 17.047552 MBytes written in 5.001168 seconds. 3.408714 MBytes/sec 

 Distribution of write time (unit is microsecond): 
 Total 2081 numbers, Sum 5001168, Min 2045, Max 33920, Avg 2403 
 From 1024 to 2047                  1 numbers 
 From 2048 to 4095               2024 numbers 
 From 4096 to 8191                 38 numbers 
 From 8192 to 16383                15 numbers 
 From 16384 to 32767                2 numbers 
 From 32768 to 65535                1 numbers

图中的例子,写操作大小为 2 个页(每个页为 4096 字节),日志文件所在目录为 /u/sfbao,测试时间为 5 秒钟。可以看出来,写磁盘的速度为 3.408714 MBytes/sec。通过模拟器的帮助我们可以看出来,disk 这个选项需要两个参数,其中一个参数是磁盘的写速度,另外一个参数是每一次写操作的额外开销,通常是指系统调用的时间。通过以上结果,我们可这样计算:(0.002403 sec/write - ((2 pages/write) / (3.408714 MBytes/sec))) = 0.000056 sec/write。也就是每一次写操作会有 0.000056 秒的开销。

可以想象,如果 flushsize 增加,每次写磁盘数据量就会变大,写操作的数量就会减少,势必对性能影响很大。下面我们来测试一下 flushsize 为 8 页的时候的效率:

 sfbao@petrel:~>./simhadr.Linux -t 5 -testDisk /u/sfbao/ -flushsize 8 
 + simhadr -t 5 -testDisk /u/sfbao/ -flushsize 8 

 Measured sleep overhead: 0.003612 second, using spin time 0.004334 second. 

 Writing to file /u/sfbao//simhadr.tmp 
 Press Ctrl-C to stop. 

 Total 1459 writes in 5.000153 seconds, 0.003427 sec/write, 8 pages/write 

 Total 47.808512 MBytes written in 5.000153 seconds. 9.561410 MBytes/sec

效率提高了近三倍,那么我们如何对我们的实际应用增加 flushsize 呢?一般来说,flushsize 取决于应用提交的频率以及应用操作的特点。例如,如果将多条语句包含在同一个存储过程中进行一次提交,flushsize 将会比多次提交这些语句大。另外,DB2 提供了一个参数 MINCOMMIT,这个参数可以控制将多个事务同时提交。注意,作者只是将这个参数指出来,并不鼓励大家在应用中使用。使用前,请咨询 IBM 的相关部门。

测试同步模式对 HADR 的影响

HADR 模拟器在主数据库端指定同步模式。例如模拟同步模式,使用命令:

 sfbao@petrel:~>./simhadr.Linux -role primary -lhost petrel -lport 54321 
 -rhost grebe -rport 54321 -t 10 -syncmode SYNC -disk 3.408714 0.000056 
 -flushsize 2 
 + simhadr -role primary -lhost petrel -lport 54321 -rhost grebe -rport 54321 
 -t 10 -syncmode SYNC -disk 3.408714 0.000056 -flushsize 2 

 Measured sleep overhead: 0.003730 second, using spin time 0.004476 second. 

 Resolving local host petrel via gethostbyname() 
 hostname=petrel.beaverton.ibm.com 
 alias: petrel 
 address_type=2 address_length=4 
 address: 9.47.73.36 

 Resolving remote host grebe via gethostbyname() 
 hostname=grebe.beaverton.ibm.com 
 alias: grebe 
 address_type=2 address_length=4 
 address: 9.47.73.43 

 Socket property upon creation 
 BlockingIO=true 
 NAGLE=true 
 SO_SNDBUF=16384 
 SO_RCVBUF=87380 
 SO_LINGER: onoff=0, length=0 

 Binding socket to local address. 
 Listening on local host TCP port 54321

模拟器的主端启动以后,就会输出以上结果,并且等待备端的连接。接下来,使用这个命令启动备端:

 sfbao@grebe:~>./simhadr.Linux -role standby -lhost petrel -lport 54321 
 -rhost petrel -rport 54321 -disk 3.408714 0.000056 
 + simhadr -role standby -lhost petrel -lport 54321 -rhost petrel 
 -rport 54321 -disk 3.408714 0.000056 

 Measured sleep overhead: 0.003634 second, using spin time 0.004360 second. 
……
……
 Received handshake message: 
 syncMode=SYNC 
 flushSize=2 
 connTime=2010-07-29_18:56:18_PDT 

 Standby receive buffer size 8 pages (32768 bytes) 
 Receiving log flushes. Press Ctrl-C on primary to stop. 
 Zero byte received. Remote end closed connection. 

 SYNC: Total 15933440 bytes in 10.001581 seconds, 1.593092 MBytes/sec 
 Total 1945 flushes, 0.005142 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 15933440 bytes written in 4.835665 seconds. 3.294984 MBytes/sec 
 Total 2907 write calls, 5.481 kBytes/write, 0.001663 sec/write 

 Total 93360 bytes sent in 10.001581 seconds. 0.009335 MBytes/sec 
 Total 1945 send calls, 0.048 KBytes/send, 
 Total 0 congestions, 0.000000 seconds, 0.000000 second/congestion 

 Total 15933440 bytes recv in 10.001581 seconds. 1.593092 MBytes/sec 
 Total 3877 recv calls, 4.109 KBytes/recv 

 Distribution of log write size (unit is byte): 
 Total 2907 numbers, Sum 15933440, Min 4096, Max 8192, Avg 5481 
 Exactly       8192         983 numbers 
 Exactly       4096        1924 numbers 

 Distribution of send size (unit is byte): 
 Total 1945 numbers, Sum 93360, Min 48, Max 48, Avg 48 
 Exactly         48        1945 numbers 

 Distribution of recv size (unit is byte): 
 Total 3877 numbers, Sum 15933440, Min 952, Max 8192, Avg 4109 
 From 512 to 1023                   9 numbers 
 From 1024 to 2047                 27 numbers 
 From 2048 to 4095               1900 numbers 
 From 4096 to 8191               1923 numbers 
 From 8192 to 16383                18 numbers

从备端的输出我们可以看出来,模拟器每秒钟实际接收 1.593092M 的日志。接下来,我们看一下主端的输出,由于篇幅原因,作者只附上部分输出:

 SYNC: Total 15933440 bytes in 10.001588 seconds, 1.593091 MBytes/sec 
 Total 1945 flushes, 0.005142 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 15933440 bytes written in 4.782755 seconds. 3.331436 MBytes/sec 
 Total 1945 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 15933440 bytes sent in 10.001588 seconds. 1.593091 MBytes/sec 
 Total 1945 send calls, 8.192 KBytes/send, 
 Total 0 congestions, 0.000000 seconds, 0.000000 second/congestion 

 Total 93360 bytes recv in 10.001588 seconds. 0.009335 MBytes/sec 
 Total 1945 recv calls, 0.048 KBytes/recv

这里,我们可以看出来主端写操作的数量以及发送日志的次数。我们发现虽然写操作可以达到 3.331436M/s 的速度,但是由于网络传送只有 1.593091M/s,所以 HADR 的整体性能必不能达到最优。

接下来是近同步模式下主机的输出,我们发现,网络发送效率提高了很多,这是在近同步模式下,日志不必写到磁盘上以后再回复 ACK。

 NEARSYNC: Total 33071104 bytes in 10.001497 seconds, 3.306615 MBytes/sec 
 Total 4037 flushes, 0.002477 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 33071104 bytes written in 9.926983 seconds. 3.331436 MBytes/sec 
 Total 4037 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 33071104 bytes sent in 10.001497 seconds. 3.306615 MBytes/sec 
 Total 4037 send calls, 8.192 KBytes/send, 
 Total 0 congestions, 0.000000 seconds, 0.000000 second/congestion 

 Total 193776 bytes recv in 10.001497 seconds. 0.019375 MBytes/sec 
 Total 4037 recv calls, 0.048 KBytes/recv

接下来是异步模式下的结果,和近同步模式相比,异步模式下的效率并没有提高很多,说明网络 RTT(Round Trip Time)并不大。考虑到可靠性和效率,我们可以选择近同步模式。

 ASYNC: Total 33284096 bytes in 10.000655 seconds, 3.328192 MBytes/sec 
 Total 4063 flushes, 0.002461 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 33284096 bytes written in 9.990917 seconds. 3.331436 MBytes/sec 
 Total 4063 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 33284096 bytes sent in 10.000655 seconds. 3.328192 MBytes/sec 
 Total 4064 send calls, 8.189 KBytes/send, 
 Total 0 congestions, 0.000000 seconds, 0.000000 second/congestion 

 Total 0 bytes recv in 10.000655 seconds. 0.000000 MBytes/sec 
 Total 0 recv calls, 0.000 KBytes/recv

测试 TCP 窗口大小对 HADR 的影响

TCP 窗口大小对应的参数是 DB2_HADR_SOSNDBUF 和 DB2_HADR_SORCVBUF。可以使用 DB2SET 命令来设置这两个值。关于这两个参数的作用,请参考 HADR 性能调优。

值得注意的是,这个参数和网络的 RTT 关系很大,如果您的网络 RTT 比较大,也就是说主端和备端的距离比较远,这个参数是很有用的。

接下来,我们通过模拟器来验证这两个参数的作用,并且找到最优值。以下输出为部分输出。

 sfbao@petrel:~>./simhadr.Linux -role primary -lhost petrel -lport 54321 
 -rhost grebe -rport 54321 -t 10 -syncmode NEARSYNC -disk 3.408714 0.000056 
 -flushsize 2 -sockSndBuf 256 -sockRcvBuf 256 
 SO_SNDBUF=2048 
 SO_RCVBUF=512 
 SO_LINGER: onoff=0, length=0 

 Sending handshake message: 
 syncMode=NEARSYNC 
 flushSize=2 
 connTime=2010-07-29_20:04:50_PDT 

 Sending log flushes. Press Ctrl-C to stop. 

 NEARSYNC: Total 17530880 bytes in 10.003095 seconds, 1.752546 MBytes/sec 
 Total 2140 flushes, 0.004674 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 17530880 bytes written in 5.262260 seconds. 3.331436 MBytes/sec 
 Total 2140 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 17530880 bytes sent in 10.003095 seconds. 1.752546 MBytes/sec 
 Total 44933 send calls, 0.390 KBytes/send, 
 Total 42786 congestions, 9.505938 seconds, 0.000222 second/congestion 

 Total 102720 bytes recv in 10.003095 seconds. 0.010269 MBytes/sec 
 Total 2140 recv calls, 0.048 KBytes/recv

上面的结果显示,虽然我们将 TCP 的接收和发送缓存都设置成了 256K,但是实际的接收缓存是 512K,发送缓存为 2048K。这里我们需要注意,虽然程序里面可以对缓冲区大小进行设置,但是最大值和最小值都不能超过内核所允许的最大和最小值。

接下来,将这两个参数增大。我们发现,当 TCP 的发送和接收缓存都设置为 4096K 的时候,总体的吞吐量增长到了 2.918185 MBytes/sec。

 ./simhadr.Linux -role primary -lhost petrel -lport 54321 
 -rhost grebe -rport 54321 -t 10 -syncmode NEARSYNC -disk 3.408714 0.000056 
 -flushsize 2 -sockSndBuf 1024 -sockRcvBuf 1024 

 SO_SNDBUF=4096 
 SO_RCVBUF=4096 
 SO_LINGER: onoff=0, length=0 

 Sending handshake message: 
 syncMode=NEARSYNC 
 flushSize=2 
 connTime=2010-07-29_23:42:05_PDT 

 Sending log flushes. Press Ctrl-C to stop. 

 NEARSYNC: Total 29188096 bytes in 10.002140 seconds, 2.918185 MBytes/sec 
 Total 3563 flushes, 0.002807 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 29188096 bytes written in 8.761417 seconds. 3.331436 MBytes/sec 
 Total 3563 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 29188096 bytes sent in 10.002140 seconds. 2.918185 MBytes/sec 
 Total 10869 send calls, 2.685 KBytes/send, 
 Total 7306 congestions, 1.401652 seconds, 0.000191 second/congestion 

 Total 171024 bytes recv in 10.002140 seconds. 0.017099 MBytes/sec 
 Total 3563 recv calls, 0.048 KBytes/recv

我们继续将这个值增加,会发现当这个值到一定程度的时候,总体的吞吐量并不会随着缓存的增加而继续增加。而这个值就是我们所需要的最优值。为了节省篇幅,作者就不再将输出展现出来。

测试 HADR 缓存对性能的影响

HADR 的缓存区只存在于备端数据库,它的作用就是对备库收到的日志进行保存,需要的时候这些日志再写入磁盘。在真实的 HADR 环境里面,这些日志被写到磁盘并且被重做完以后才从缓冲区中删除。所以,如果某段时间内主端产生了大量日志,而备端重做的又比较慢,这个参数就很重要了。因为如果缓冲区不够大,导致 100% 的使用率,那么主端数据库的日志就不能发送到备端数据库,进而导致主数据库的事务被阻塞。在 HADR 模拟器中,缓冲区的设置选项是 -hadrBufSize。它对应真实 HADR 里面的 DB2_HADR_BUF_SIZE,可以使用 DB2SET 对该值进行设置,最大值为 2G。

而真实 HADR 缓冲区的使用率可以使用 db2pd 进行监控,如以下输出:

 sfbao@grebe:~>db2pd -db hadrdb -hadr 

 Database Partition 0 -- Database HADRDB -- Active -- Up 0 days 00:00:30 
 -- Date 08/11/2010 07:50:21 

 HADR Information: 
 Role    State                SyncMode HeartBeatsMissed   LogGapRunAvg (bytes) 
 Standby Peer                 Nearsync 0                  0                   

 ConnectStatus ConnectTime                           Timeout   
 Connected     Wed Aug 11 07:50:16 2010 (1281538216) 120       

 PeerWindowEnd                         PeerWindow 
 Wed Aug 11 07:50:30 2010 (1281538230) 10        

 LocalHost                                LocalService      
 grebe                                    54321             

 RemoteHost                               RemoteService      RemoteInstance    
 petrel                                   54321              sfbao             

 PrimaryFile  PrimaryPg  PrimaryLSN        
 S0000617.LOG 0          0x0000000001D2C000 

 StandByFile  StandByPg  StandByLSN         StandByRcvBufUsed 
 S0000617.LOG 0          0x0000000001D2C000 0%

在 HADR 环境中,缓冲区的默认大小是日志缓冲区大小的两倍,这也是我们建议的最小值。最优值要根据事务的特征和软硬件环境决定。基本的原则是,如果发现缓冲区的使用率达到了 100%,就需要调大一些。只要缓冲区的使用率不经常达到 100%,就不会对性能带来影响。

以下试验中,我们将 hadrBufSize 分别设置为 4 个 PAGE 和 8 个 PAGE。输出结果如下:

 NEARSYNC: Total 33087488 bytes in 10.001522 seconds, 3.308245 MBytes/sec 
 Total 4039 flushes, 0.002476 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 33087488 bytes written in 9.931901 seconds. 3.331436 MBytes/sec 
 Total 4039 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 33087488 bytes sent in 10.001522 seconds. 3.308245 MBytes/sec 
 Total 4039 send calls, 8.192 KBytes/send, 
 Total 0 congestions, 0.000000 seconds, 0.000000 second/congestion 

 Total 193872 bytes recv in 10.001522 seconds. 0.019384 MBytes/sec 
 Total 4039 recv calls, 0.048 Kbytes/recv

以下为 hadrBufSize 为 8 个 page 的时候的效率:

 NEARSYNC: Total 33062912 bytes in 10.000452 seconds, 3.306142 MBytes/sec 
 Total 4036 flushes, 0.002478 sec/flush, 2 pages (8192 bytes)/flush 

 disk speed: 3.408714 MB/second, overhead: 0.000056 second/write 
 Total 33062912 bytes written in 9.924524 seconds. 3.331436 MBytes/sec 
 Total 4036 write calls, 8.192 kBytes/write, 0.002459 sec/write 

 Total 33062912 bytes sent in 10.000452 seconds. 3.306142 MBytes/sec 
 Total 4036 send calls, 8.192 KBytes/send, 
 Total 0 congestions, 0.000000 seconds, 0.000000 second/congestion 

 Total 193728 bytes recv in 10.000452 seconds. 0.019372 MBytes/sec 
 Total 4036 recv calls, 0.048 Kbytes/recv

我们可以看出来,缓冲区的增大并没有使得日志传输的效率提高。因为当缓冲区为 4 个 PAGE 的时候,就已经足够了。

总结

本文列举了 DB2 HADR 在工作工程中可能遇到的性能问题,并且根据情况提出了可能的解决办法。本文还对 HADR 模拟器进行了介绍,给出了几个使用 HADR 模拟器的实例。并且描述了如何使用该工具模拟 HADR 工作,从而确定 HADR 性能参数的最优值。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值