oracle rac HA and LB


1.        FAILOVER

FAILOVER就是着集群中任何一个节点的故障都不会影响用户使用,连接到故障节点的用户会被自动转移到健康节点,从用户感受而言感觉不到这种切换,这个功能在oracle中被称作FAILOVER.

ORACLE 10g的FAILOVER 可以细分为三种:

l  Client-side Connect time Failover

l  TAF

l  Service-Side TAF

注意:不要在listener.ora 中设置GLOBAL_DB_NAME,因为这个参数会禁用Connect-time Failover 和 Transparent Application Failover

1.1.       client-side connect time failover

含义是:如果用户端tnsnames中配置了多个地址,用户发起连接请求时,会先尝试连接地址表中的第一个地址,如果连接尝试失败,则继续尝试使用第二个地址,直至连接成功或者遍历了所有的地址。

这种failover的特点只在发起连接时才去感知节点故障,如果发现节点没有响应,则自动尝试地址列表中的下一个地址。一旦连接建立以后,节点出现故障都不会作出处理,从客户端的表现就是会话断开,用户程序必须重新建立连接。

启用这种Failover的方式就是在客户端的tnsnames.ora中添加FAILOVER=on 条目,这个参数默认是ON,所以即使不添加这个条目,客户端也会获得这种能力。

1.2.       TAF

所谓TAF,就是连接建立以后、应用系统运行过程中,如果某个实例发生故障,连接到这个实例上的用户会被迁移到其他的健康实例上。对于应用程序而言,这个迁移过程透明,不需要用户的介入,当然这种透明也是有引号的,因为用户的位提交事务会回滚。

TAF的配置只需要在客户端的tnsnames.ora中添加FAILOVER_MODE配置项,这个条目中有四个子项目需要定义。

a)        METHORD选项用于定义何时创建到其他实例的连接,有BASIC 和PRECONNECT 两个可选值。

l  BASIC 是指在感知到节点故障时才创建到其它实例的连接。

l  PRECONNECT是在最初建立连接时就同时建立到所有实例的连接,当发生故障时,立刻切换到其它链路上。

                 两种方法的比较:BASIC会有时间延迟,PRECONNECT方式虽然没有时间延迟,但是建立多个冗余连接会消耗更多资源,两者就是用时间换资源和用资源换时间的区别。

b)        Type选项用于定义发生故障时对完成的SQL语句如何处理,其有两种类型:session和select。

这两种方式对于未提交事务都会自动回滚。区别在于对select语句的处理,对于后一种类型,用户正在执行的select语句会被转移到新的实例上,在新节点上继续返回后续结果集,而已经返回的记录集抛弃。

为了实现这种select方式,oracle 必须为每个session保存更多的内容,包括游标、用户上下文等。需要更多的资源也是用资源换时间的方案。

c)        DEALY 和RETRIES 代表重试时间和重试次数

1.2.1.      Client-Side Connect TimeFailover 和TAF的对照试验

测试流程:

(一)  一个两个节点RAC,节点分别是 NODE1-VIP ,NODE2-VIP

(二)  客户端的TNSNAMES.ORA分别配置两个条目,分别使用两种FAILOVER

(三)  客户端利用这两个tnsnames条目,打开两个窗口,建立两个链接,做操作

(四)  在服务器上,用kill命令杀掉两个链接对应的Server process 来模拟节点故障(也可以使用重启节点的方式)

(五)  经过短暂实践后,使用TAF的连接会自动转移到其它实例上,用户可以继续在这个窗口执行语句;

(六)  而使用client-side connect time failover 的连接不会自动转移,用户必须重新连接。

1.2.2.      测试步骤

(一)  编辑客户端tnsnames.ora文件,在其中添加两个条目,分别使用两种Failover 机制:wsxdb_cl 对应Client-side 而wsxdb_taf 对应TAF。两个条目中都没设置FAILOVER=ON选项默认就是ON。

wsxdb_cl=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

    )

  )

 

 

wsxdb_taf=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

      (FAILOVER_MODE =

        (TYPE = session)

        (METHOD = basic)

        (RETRIES = 180)

        (DELAY = 5)

      )

    )

 )

 

 

 

 

(二)  开启两个窗口,分别使用两个TNS进行连接,为了区分这两个连接,这里使用不同的用户登陆。

 第一个窗口使用client-side

SQL>conn scott/tiger@wsxdb_cl

 第二个窗口使用 TAF

SQL>conn hr/hr@wsxdb_taf

(三)  连接成功后,在两个窗口执行语句。

在第一个窗口中查看用户连接到的实例

SQL>select instance_name from v$instance;

 

INSTANCE_NAME

--------------------------------

    rac2

查看用户连接的TAF配置

SQL>select username,failover_type,failover_method from v$session

  2 where username in ('HR','SCOTT' );

 

USERNAME

------------------------------------------------------------

FAILOVER_TYPE              FAILOVER_METHOD

----------------------------------------------

SCOTT

    NONE                       NONE

查询结构都为NONE说明这个连接没有使用TAF

在第二个窗口中,查看用户连接的实例

SQL>  select instance_name from v$instance;

 

INSTANCE_NAME

--------------------------------

   rac1

查看用户连接的TAF和TNS配置中相符

  1 select username,failover_type,failover_method from v$session

  2*    where username in ('HR','SCOTT' )

SQL>/

 

USERNAME

------------------------------------------------------------

FAILOVER_TYPE              FAILOVER_METHOD

----------------------------------------------

HR

    SESSION                    BASIC

(四)  在服务端杀掉两个连接对应的Server Process

查看两个连接对应的Server process的OS PID

 

SQL>select spid from v$session a,v$process b where a.paddr=b.addr anda.username='HR';

 

SPID

------------

   13950

 

SQL>select spid from v$session a,v$process b where a.paddr=b.addr anda.username='SCOTT';

 

SPID

------------

  20946

[root@node1 ~]# ps aux |grep 13950|grep -v grep

oracle   13950 0.0  4.5 426716 46284 ?        Ss  05:18   0:00 oraclerac1 (LOCAL=NO)

 

[root@node2 ~]# ps aux |grep20946|grep -v grep

oracle   20946 0.0  5.7 426916 59264 ?        Ss  05:16   0:00 oraclerac2 (LOCAL=NO)

使用kill -9杀掉两个OS PID

[root@node1 ~]# kill -9 13950

[root@node2 ~]# kill -9 20946

(五)  返回到两个窗口,再实行sql语句,两个连接都报同样的错误

SQL>select instance_name from v$instance;

selectinstance_name from v$instance

*

第 1 行出现错误:

  ORA-03113: 通信通道的文件结束

(六)  稍等几秒后再次执行语句

第一个窗口

SQL>select instance_name from v$instance;

ERROR:

   ORA-03114: 未连接到 ORALCE

第二个窗口

SQL>  select instance_name from v$instance;

 

INSTANCE_NAME

--------------------------------

    rac2

第一个窗口需要重新连接(连接时故障转移)

第二个窗口过了一段时间后迁移到另一个实例

1.2.3.      测试PRECONNECT

wsxdb_taf=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

      (FAILOVER_MODE =

        (TYPE = session)

        (METHOD = PRECONNECT)

        (RETRIES = 180)

        (DELAY = 5)

      )

    )

 )

 

查看连接到的实例

SQL>CONN HR/HR@WSXDB_TAF

已连接。

SQL>  select instance_name from v$instance;

 

INSTANCE_NAME

--------------------------------

  rac1

查看OS PID

SQL> select spid from v$sessiona,v$process b where a.paddr=b.addr and a.username='HR';

SPID

------------

31994

[root@node1 ~]# ps aux |grep 31994|grep -v grep

oracle   31994 0.0  2.3 424120 24556 ?        Ss  05:54   0:00 oraclerac1 (LOCAL=NO

杀掉OS PID

[root@node1 ~]# kill -9 31994

很快的切换到实例二

select instance_name from v$instance

INSTANCE_NAME

--------------------------------

  rac2

 

 

 

 

1.2.4.      测试type为select

wsxdb_taf=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

      (FAILOVER_MODE =

        (TYPE = select)

        (METHOD = basic)

        (RETRIES = 180)

        (DELAY = 5)

      )

    )

 )

SQL> conn hr/hr@wsxdb_taf

查看用户连接的实例

SQL>  select instance_name from v$instance;

 

INSTANCE_NAME

--------------------------------

   rac1

运行一个笛卡尔积,在运行过程中模拟断电shutdown abort 实例1

SQL> select last_name,salary fromemployees a,employees b;

 

模拟断电shutdown abort

SQL> shutdown abort

此时查询会停止一会,接着继续查询

查询完毕后查看用户连接的实例,以及切换到实例二。

SQL> select instance_name fromv$instance;

INSTANCE_NAME

--------------------------------

   rac2

1.3.       Service-Side TAF

Server-Side TAF 也是TAF,所有TAF有的特点它都具有;其次这种TAF是在服务器上配置,而不像TAF是在客户端配置。

Server-side TAF 通过结合Service,在数据库里保存FAIL_MODE的配置,把所有的TAF配置保存在数据字典,从而省去了客户端的配置工作,现在客户端的TNS文件就不需要任何TAF的配置选项了。

从配置参数而言,Server-side TAF 和TAF相比多了一个INSTANCE role(实例角色)的概念。所谓实例角色就是当有多个instance 参与一个service时,可以配置优先使用哪一个instance为用户提供服务。用户共有两种可选角色。

l  PREFERRED:首选实例,会优先选择拥有这个歌角色的实例提供服务。

l  AVAILABLE:后备实例,用户连接会优先连接PREGERRED的instance,当PREFERRED的instance 不可用时,才会被转到AVAILABE的instance上。

要想使用Server-side TAF 必须配置Service。Service 可以在创建数据库时创建,也可以在数据库创建之后修改;既可以通过配置向导,也可以通过命令行方式配置。

1.3.1.      使用srvctl命令配置service

1.        创建service

srvctl add service -ddatabase_name  -s service_name  -r "preferred-instance" -a "avaliable-instance"  -P<TAF_POLICY>

其中TAF-POLICY 选项可以为BASIC 或PRECONNECT。

2.        查看配置

srvctl  config service -d database-name   [-s service-name]  [-a]

如果不指定“-s service-name”就会显示所有的service 配置,这些配置只包括preferred 和available

3.        是否自动运行service

数据库启动时会自动启动所有的service。有时为了维护的需要,需要禁用这个特性。在维护完成后再启动这个特性。

srvctl enable/disable  service -d database-name -s service-name -iinstance-name

4.        启动service

srvctl start  service -d database-name  -s  service-name -i  instance-name -o  startoption -c  connect-string  -q

如果不指定service-name 则所有的service都会被启动;可以使用逗号分隔方式,同时启动多个service。-i 指定在哪个实例上启动service。

5.        停止service

srvctl stop  service -d database-name  -s  service-name -c  connect-string -q -f

其中-f选项可以强制关闭service ,并中断了其所有的用户连接。

6.        查看service状态

srvctl  status service  -d database-name  -s service-name -f  -v

7.        删除service

srvctl  remove  service  -d database-name  -s service-name   -i instance  -f 

在使用srvctl 创建service时,必须要注意TAF策略必须通过dbms_service 包来配置。

1)        再添加服务之前,查看系统现有的service

SQL> show parameter service

NAME                                 TYPE        VALUE

------------------------------------ -----------------------------------------

service_names                        string      ocm.oracle.com

2)        使用srvctl创建一个wsx服务

[oracle@node1 ~]$ srvctl add service-d ocm -s wsx -r rac1 -a rac2 -P basic

srvctl add service中,只有perferred才会创建服务。 即在OCR中注册一个ora.ocm.wsx.rac1.Srv的服务。

3)        查看服务

[oracle@node1~]$ crs_stat -t -v

Name           Type           R/RA   F/FT  Target    State     Host       

----------------------------------------------------------------------

省略输出     

ora.ocm.wsx.cs application   0/0    0/1    OFFLINE  OFFLINE              

     ora....ac1.srv application    0/0   0/0    OFFLINE   OFFLINE

            ora....ac2.srv application    0/0   0/0    ONLINE    OFFLINE   node2

4)        配置服务自动启动

[oracle@node1~]$ srvctl enable service -d ocm -s wsx

   PRKP-1018 : Service wsx already enabled.

5)        启动服务,并查看状态,状态时ONLINE 说明已经启动

[oracle@node1~]$ srvctl start  service -d ocm -s wsx

[oracle@node1~]$ crs_stat -t -v

   省略输出    

ora.ocm.wsx.csapplication    0/0    0/1   ONLINE    ONLINE    node1      

ora....ac1.srv application    0/0   0/0    ONLINE    ONLINE   node1

6)        新创建的服务会自动添加到初始化参数中

SQL>  show parameter service

NAME                                 TYPE        VALUE

----------------------------------------------- ------------------------------

 service_names                       string      ocm.oracle.com, wsx

7)        修改Service的TAF配置需要使用dbms_service.modify_service

SQL>begin

   dbms_service.modify_service(

    service_name => 'wsx',

    failover_method=>dbms_service.failover_method_basic,   

    failover_type=>dbms_service.failover_type_select,

    failover_retries => 180,

    failover_delay=>5

    );

    end;

 10  /

8)        确认参数已经生效

SQL>  select name,failover_method,failover_typefrom dba_services;

wsx       basic select

9)        使用srvctl 查看服务配置

[oracle@node1 admin]$ srvctl configservice -d ocm -s wsx

wsx PREF: rac1 rac2 AVAIL:

10)    查看监听器

Service "wsx.oracle.com" has 2 instance(s).

  Instance "rac1", status READY, has2 handler(s) for this service...

    Handler(s):

      "DEDICATED" established:0refused:0 state:ready

         LOCAL SERVER

      "DEDICATED" established:0refused:0 state:ready

         REMOTE SERVER

         (ADDRESS=(PROTOCOL=TCP)(HOST=node1.example.com)(PORT=1521))

  Instance "rac2", status READY, has1 handler(s) for this service...

    Handler(s):

      "DEDICATED" established:2refused:0 state:ready

         REMOTE SERVER

        (ADDRESS=(PROTOCOL=TCP)(HOST=node2.example.com)(PORT=1521))

The command completed successfully

1.4.       配置Service 的注意事项

 1). 数据库的服务名是用service_name 参数来指定的,一个数据库可以有多个服务名,但是service_name最长是4kb,不要手工来修改这个参数

 2最多可以创建64个service,每个数据库有2个隐含的service,因此留给用户的就只有62个service。不能修改这两个隐含service的配置,并且也不能手工启动或停止这2个服务。 这两个隐含的service分别是:SYS$BACKGROUND 和 SYS$USERS.

 3) 当使用dbca配置Service 时,dbca 会自动更新OCR,启动Service, 当删除service时,会停止service,并更新OCR.

 4) 使用srvctl 这个工具时,命令只更新OCR中的配置,不会更新data dctionary 和 listener 中的信息,因此还需要使用dbma_servie 包来更新data dictionary,手工更改listener配置文件。 故推荐使用DBCA工具来配置更改service配置

 5 如果客户端想通过Service 方式连接数据库,需要在tns条目中使用service_name 方式引用数据库。 如:

RAC =

  (DESCRIPTION =

     (ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521))

     (ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))

      (LOAD_BALANCE=YES)

      (

   CONNECT_DATA=

    (SERVER=DEDICATED)

(SERVICE_NAME=RAC)

     )

1.5.     测试Service-Side TAF

客户端tnsnames.ora内容

wsxdb=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME=wsx.oracle.com)

    )

l 从客户端连接

SQL> conn hr/hr@wsxdb

l  查询当前用户连接到的实例

SQL>select instance_name from v$instance;

INSTANCE_NAME

--------------------------------

rac2

l  在实例2上模拟断电

SQL>shutdown abort

l  执行查询语句

SQL>select instance_name from v$instance;

 

INSTANCE_NAME

--------------------------------

rac1

删除服务

删除服务之前先停止服务

[oracle@node2~]$ srvctl stop service -d ocm -s wsx

[oracle@node2~]$ srvctl disable  service -d ocm -s wsx

删除服务

[oracle@node2~]$ srvctl remove  service -d ocm -s wsx

wsxPREF: rac1 AVAIL: rac2

Servicewsx is disabled.

Removeservice wsx from the database ocm? (y/[n]) y

OCR中的内容被删除,但是数据字典里还有该Service的内容,继续清除数据字典里的内容

SQL>  selectname,failover_method,failover_type from dba_services;

wsx       basic  select

删除数据字典内容

SQL>begin

  2 dbms_service.delete_service(service_name=>'wsx');

  3  end;

  4  /

 

2.     LOADBALANCE

2.1.     CONNECTION BALANCING

这种负载均衡时在用户连接这个层次上进行的,也就是在用户请求建立连接时,根据每个节点的负载决定把连接分配到哪个实例上。而一旦建立之后,会话的所有操作就都在这个实例上完成,而不会在分配到其他实例上。

ConnectionBalancing 有客户端和服务器端两种实现方法。

l  客户端均衡

客户端均衡时ORACLE 8使用的方法,配置方法师在客户端的tnsnames.ora文件中假如LOAD_BALANCE=YES条目。当客户端发起连接时,会从地址列表中随机选取一个地址,再使用随机算法把连接请求分散到各个实例。

这种配置方法,因为在分配连接时没有考虑每个节点的真实负载,最后分配结果不一定是平衡的;并且随机算法需要长时间片,如果哦在短时间内同时发起多个连接,这些连接有可能被分配到一个节点上;甚至更坏的情况下,连接可能会被分配到故障节点上。因此oracle又引入了 服务器端均衡方式。

l  服务器端均衡(server-sideLB)

服务器端负载均衡的实现依赖于listener 收集的负载信息,。在数据库运行过程中,PMON后台进程会收集系统的负载信息,然后登记到listener中。最少一分钟,最多十分钟PMON就要做一次信息更新,并且如果节点的负载越高,更新频率就越高 ,以保证listener 能够掌握没个节点准确的负载情况。如果listener关闭,PMON进程会每隔1秒钟检查listener是否重启。除了这个自动的、定时的更新任务外,用户也可以使用altersystem register 命令来手工进行这个过程。

这个自动更新动作,可以从LISTENER 的日志中看到(

/u01/app/oracle/product/10.2.0/db_1/network/log)。当实例启动时PMON进程进行的第一次登记过程叫做server-regiser而后的更新叫做service-update

listener日志虽然记录了PMON进程的注册和更新动作,但是注册的内容却没有体现,要想获得这些内容,可以通过10257事件来获得,这个时间就是跟踪PMON活动。

SQL>  select spid ,program from v$process whereprogram like '%PMON%';

 

SPID         PROGRAM

------------------------------------------------------------

1893         oracle@node1.example.com (PMON)

 

SQL>oradebug setospid 1893

Oraclepid: 2, Unix process pid: 1893, image: oracle@node1.example.com (PMON)

SQL>oradebug event 10257 trace name context forever,level 16;

SQL>alter system register;

SQL>oradebug event 10257 trace name context off;

SQL>oradebug tracefile_name;

/u01/app/oracle/admin/ocm/bdump/rac1_pmon_1893.trc

PMON进程不仅会向本地的listener注册,还可以向其他节点上的litener注册。但到底是要想何处注册,是由Remote_listener和local_listener这两个参数决定。local_listener不用设置,而remote_listener需要设置, 是一个tnsname项

有了PMON的自动注册机制后,集群的每个节点的listener都掌握所有节点的负载状态,当收到客户端连接请求时,就会把连接转给负载最小的节点,这个节点有可能是自己也有可能是其它节点,也就是listener会转发用户的连接请求。listener的节点选择方法根据用户所请求的连接方式会有所不同:

l  如果用户请求的是dedicated专有连接,listener 首先选择负载最小的节点,如果多个节点负载相同,则从中选择负载最小的实例。

l  如果用户请求的是sharedserver 共享连接,除了做节点负载比较和实例负载比较之外,还要所选择的实例上,选择负载最小的dispatcher进行转发

server-sideLB 和client-sideLB二者可以互相工作,这是用户的连接请求会先从地址列表中随机选择一个地址,然后向改地址的listener发出请求,listener 接到请求后,根据节点的负载情况挑选出最合适的节点转发连接请求.

8.     测试LoadBalance

LoadBalance是listener内部的机制,没有办法跟踪,可通过方法验证。

通过listener 日志区分路由来源

在client-sideLB 配置下,用户会从地址列表中随机选取一个Listener,发出连接请求。listener 收到连接请求后,要对这个请求进行路由。如果配置了Service-sideLB,Listener 会把这个请求路由到负载最小的实例;也就是说,Listener可能把用户请求路由到本地实例,也可能路由的其他实例。这两种来源可以从Listener日志中区分。

区分路由到本地实例和远程实例的关键点在于,Listener无论把用户请求路由到本地或远程,本地Listener日志条目都有 “establish” 字样,但是没有“instance_name”字样;而如果连接请求是由远程Listener 转发过来的,则日志条目中同时有 “instance_name”和“establish”字样。但是对于转发来的请求,没有记录这个连接是从哪个Listener转发来的。

1.1.     测试方法

测试脚本如下

[oracle@node1~]$ cat test.sh

#!/bin/sh

count=0

while[ $count -lt $2 ]

do

  count=`expr $count + 1`

 

  sqlplus -s hr/hr@$1 @test.sql

done

[oracle@node1~]$ cat test.sql

col"instance_name" format a20

selectinstance_name from v$instance

/

exit

测试client-sideLB

l  客户端的tnsnames.ora内容

wsxdb_cl=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip.example.com)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip.example.com)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

    )

    )

l  数据库的准备工作

去掉service-sdieLB 内容

SQL>alter system set remote_listener='' scope=spfile sid='*';

    重启数据库和listener

[oracle@node1~]$ srvctl  stop database -d ocm

[oracle@node1~]$ srvctl  stop listener -n node1

[oracle@node1~]$ srvctl  stop listener -n node2

[oracle@node1~]$ srvctl  start listener -n node2

[oracle@node1~]$ srvctl  start listener -n node1

[oracle@node1~]$ srvctl  start database -d ocm

重启后清空两个节点的日志

 [oracle@node1 log]$ cat /dev/null >listener_node1.log

 [oracle@node2 log]$ cat /dev/null >listener_node2.log

l  执行测试脚本,参数1000代表建立1000个连接

[oracle@node1~]$ ./test.sh wsxdb_cl 1000 >wsxdb_cl.log

l  检查结果

[oracle@node1~]$ grep rac1 wsxdb_cl.log |wc -l

465

[oracle@node1~]$ grep rac2 wsxdb_cl.log |wc -l

535

l  提取两个节点的listener日志内容

[oracle@node1log]$ grep establish listener_node1.log |wc -l

465

说明实例1共接受了465个用户连接

[oracle@node1log]$  grep -i instance_name=raclistener_node2.log |wc -l

0

说明465个连接中有0个是从实例2的listener 路由过来的,也就是说客户端发出了483个到实例1的连接请求

[or

[oracle@node2log]$  grep establish listener_node2.log|wc -l

535

说明实例1共接受了535个用户连接

[oracle@node2log]$  grep -i instance_name=raclistener_node2.log |wc -l

0

说明535个连接中有0个是从实例1的listener 路由过来的,也就是说客户端发出了535个到实例2的连接请求

以上是用了Client-sideLoad Balance ,也就是客户端从TNS地址列表中随机选择实例发送请求。

1.2.     测试单纯的Server-sideLB

l  准备客户端tnsnames.ora内容,关闭client-sideLB及两个实例的listener.ora的内容

注释掉各个实例中缺省的sid_list_listener_name条目,这样才能保证listener 获得的信息都是动态注册的,而不是从文件中读取信息

#SID_LIST_LISTENER_NODE2=

#  (SID_LIST =

 #  (SID_DESC =

  #   (SID_NAME = PLSExtProc)

   #  (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1)

   #  (PROGRAM = extproc)

   # )

 # )

wsxdb_cl=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip.example.com)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip.example.com)(PORT = 1521))

    (LOAD_BALANCE = off)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

    )

    )

l  数据库端准备工作

SQL>alter system set remote_listener='LISTENERS_OCM' scope=spfile sid='*';

[oracle@node1~]$ srvctl stop database -d ocm

[oracle@node1~]$ srvctl stop listener -n node1

[oracle@node1~]$ srvctl stop listener -n node2

[oracle@node1~]$ srvctl start listener -n node2

[oracle@node1~]$ srvctl start listener -n node1

[oracle@node1~]$ srvctl start  database -d ocm

清空两个节点的日志

 [oracle@node1 log]$ cat /dev/null >listener_node1.log

 [oracle@node2 log]$ cat /dev/null >listener_node2.log

l  执行测试脚本

l  测试结果

 

实例1

[oracle@node1log]$ grep establish listener_node1.log |wc -l

1000

[oracle@node1log]$ grep -i instance_name=rac listener_node1.log |wc -l

0

一共接受了1000个用户的连接请求,其中有0个是从实例2的liste路由过来的。所以客户端发起了1000个到实例1的连接请求。计算client-sideLB 为1000-0=1000

实例2

[oracle@node2log]$ grep -i instance_name=rac listener_node2.log |wc -l

417

[oracle@node2log]$ grep establish listener_node2.log |wc -l

417

说明一个接受了417个用户连接。其中417个是从实例1的listener路由过来的。计算client-sideLB为417-417=0,即客户端发出了0个到实例2的连接请求。

在这个中客户端的tnsnames.ora配置中,使用LOAD_BALANCE=off,禁用了client-sideLB 所以用户的1000个请求全部发给了实例1,因为在地址列表中node1-vip是放在第一条。

l  Listener路由到实例的连接请求数:实例1:1000-417=583,实例2:=0-0=0

l  远程的listener路由到本实例的连接请求数:实例1:0 实例2:=417

l  Server-sideLB 的分配 583/417

1.3.     测试混合的client-sideserver-side LB

客户端tnsnames.ora

wsxdb_cl=

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST =node1-vip.example.com)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =node2-vip.example.com)(PORT = 1521))

    (LOAD_BALANCE = yes)

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = ocm.oracle.com)

    )

数据库端

SQL>alter system set remote_listener='LISTENERS_OCM' scope=spfile sid='*';

[oracle@node1~]$ srvctl stop database -d ocm

[oracle@node1~]$ srvctl stop listener -n node1

[oracle@node1~]$ srvctl stop listener -n node2

[oracle@node1~]$ srvctl start listener -n node2

[oracle@node1~]$ srvctl start listener -n node1

[oracle@node1~]$ srvctl start  database -d ocm

清空两个节点的日志

 [oracle@node1 log]$ cat /dev/null >listener_node1.log

 [oracle@node2 log]$ cat /dev/null >listener_node2.log

执行测试脚本

[oracle@node1~]$ ./test.sh wsxdb_cl 1000 >wsxdb_mix.log

查看测试结果

[oracle@node1~]$ grep rac1 wsxdb_mix.log |wc -l

289

[oracle@node1~]$ grep rac2 wsxdb_mix.log |wc -l

711

实例1

[oracle@node1log]$ grep -i instance_name=rac listener_node1.log |wc -l

190

[oracle@node1log]$ grep establish listener_node1.log |wc -l

656

共接受了656个用户的连接请求其中有190个使用实例2的listener路由过来的。计算client-sideLB 656-190=466,即客户端发出了466个到实例1的连接请求

[oracle@node2log]$ grep -i instance_name=rac listener_node2.log |wc -l

367

[oracle@node2log]$ grep -i establish listener_node2.log |wc -l

901

共接受了901个用户的连接请求其中有367个使用实例1的listener路由过来的。计算client-sideLB 901-367=534,即客户端发出了534个到实例2的连接请求

这种方法混好了client-side和server-side两种LB,结果说明如下

l  client-sideLB=466/534

l  listener路由到本实例的连接请求数量:实例1466-367=99 实例2534-190=344

l  远程的listener 路由到本实例的连接请求数量:实例1190 实例2367

l  server-sideLB的分配 190/367

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值