Sunday, March 7, 2010

SCAN - Single Client Access Name in Oracle 11gr2

SCAN (Single Client Access Name) is a new feature in Oracle 11gR2. With this, Oracle is taking the High-Availability Plug and Play to the next level. Though this new feature has some advantages in a grid infrastructure setup, there seems to be some penalty in connection initiation when using the SCAN method.

Details about SCAN and it's workings can be gotten from Metalink.

History

To take a walk down the memory lane; Oracle 10g RAC provided the ability to use VIP (Virtual IP) to have a faster response to network related issues. Before this, database connections having network related disconnect issues, could indicate to the end-user about the state of the connection based on TCP timeout, as late as 10 minutes. This was overcome with the Oracle VIP wherein a virtual ip from the same subnet as the public IP was configured which would failover to one of the surviving instances instantaneously and send an error message to the client. This concept has been extended from a “virtual-ip from node-level” to a virtual-IP at cluster level. The Oracle VIP is still valid and being used in 11g. The SCAN (single client access name), provides a cluster level abstraction. The SCAN is configured to listen to incoming connections on a specific port. All cluster resources registers with this resource including the database listeners that are configured to the instances. SCAN configuration seems to be mandatory during Oracle 11gR2 install; however, it can be disabled afterwards if preferred.

The idea behind this feature is to make cluster node management easier and seamless to the underlying applications. In the past, node addition or removal meant editing listener entries and tnsnames entries in all the nodes that are part of the cluster. With virtualizing the connection information using SCAN this step is completely eliminated.

With SCAN, a simple entry for the SCAN VIP(s) and PORT# in TNSNAMES.ora entries is just enough making an exhaustive configuration not necessary.

What’s New

1. The remote_listener will always be set to the SCAN Name and Port.
2. The load balancing, failover parameters etc that were configured before is not needed as the SCAN listener by default takes care of these functions.

Configuration Setup

Below, a sample setup to show the workings of SCAN is provided. In the configuration, I have purposely used multiple variations to emphasize the point that it works rather seamlessly and the amount of setup and configuration required are very minimal.

The test database runs on a 2-node cluster/11gR2 with default setup for SCAN listener.

[grid@linux1 admin]$ srvctl status scan_listener
SCAN Listener LISTENER_SCAN1 is enabled
SCAN listener LISTENER_SCAN1 is running on node linux1
[grid@linux1 admin]$ srvctl config scan_listener
SCAN Listener LISTENER_SCAN1 exists. Port: TCP:1521

Two listeners are created one on the grid infrastructure and the other on the Oracle database homes.

[oracle@linux1 ~]$ ps -ef grep inheritgrep -v grep awk '{print $8" " $9}'
/u01/app/11.2.0/grid/bin/tnslsnr LTEST
/u01/app/11.2.0/grid/bin/tnslsnr LISTENER_SCAN1

[oracle@linux2 admin]$ ps -ef grep inheritgrep -v grep awk '{print $8" " $9}'
/u01/app/oracle/product/11.2.0/dbhome_1/bin/tnslsnr LISTENERCUSTOM

[grid@linux1 admin]$ cat endpoints_listener.ora grep LTEST
LTEST_LINUX1=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=linux1-vip)(PORT=1529))
(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.153)(PORT=1529)(IP=FIRST))))# line added by Agent

[oracle@linux2 admin]$ cat endpoints_listener.ora grep LISTENER
LISTENERCUSTOM_LINUX2=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=linux2-vip)(PORT=1522))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.155)(PORT=1522)(IP=FIRST)))) # line added by Agent

SQL> set head off
SQL> col name fold_a
SQL> select name,value from v$parameter where
2 name in ('local_listener','remote_listener','instance_name');

instance_name
GREEN2

local_listener
(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=linux2-vip)(PORT=1522))))

remote_listener
racnode-cluster-scan:1521

SQL> select name,value from v$parameter where
2 name in ('local_listener','remote_listener','instance_name');

instance_name
GREEN1

local_listener
(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=linux1-vip)(PORT=1529))))

remote_listener
racnode-cluster-scan:1521

With this setup, I make connections on a quiet (sandbox) database.

[oracle@linux1 ~]$ strace -o ltest1_t -af -tt sqlplus system/sys@green @param1 instance_name

Some Log Details sniped…

NAME VALUE SES SYS ISMOD ISADJ
----------------------------------- --------------- ----- --------- ---------- -----
instance_name GREEN1 FALSE FALSE FALSE FALSE

21:53:42.615196 connect(9, {sa_family=AF_INET, sin_port=htons(1521), sin_addr=inet_addr("192.168.1.187")}, 16) = -1 EINPROGRESS (Operation now in progress)
21:53:42.616490 getsockname(9, {sa_family=AF_INET, sin_port=htons(62112), sin_addr=inet_addr("192.168.1.187")}, [16]) = 0
21:53:42.623002 connect(9, {sa_family=AF_INET, sin_port=htons(1529), sin_addr=inet_addr("192.168.1.201")}, 16) = -1 EINPROGRESS (Operation now in progress)

Another attempt to the second instance, shows

NAME VALUE SES SYS ISMOD ISADJ
----------------------------------- --------------- ----- --------- ---------- -----
instance_name GREEN2 FALSE FALSE FALSE FALSE

[oracle@linux1 ~]$ cat ltest2_t grep inet
21:58:20.645723 connect(9, {sa_family=AF_INET, sin_port=htons(1521), sin_addr=inet_addr("192.168.1.187")}, 16) = -1 EINPROGRESS (Operation now in progress)
21:58:20.646914 getsockname(9, {sa_family=AF_INET, sin_port=htons(23662), sin_addr=inet_addr("192.168.1.187")}, [16]) = 0
21:58:20.654415 connect(9, {sa_family=AF_INET, sin_port=htons(1522), sin_addr=inet_addr("192.168.1.202")}, 16) = -1 EINPROGRESS (Operation now in progress)

If you notice, from the connection to the “GREEN1” instance, this is the local node from where the test was initiated, so the connection sort of comes back to the host. It takes 7.8 milliseconds (623002-615196)/1000 and for the connection that has to go to a remote instance, in our case “GREEN2”, it is 8.6 milliseconds.

Just to prove that there is an overhead with SCAN, I ran another test with the 10g-like setup.

[oracle@linux1 ~]$ strace -o oldstyl1 -af -tt sqlplus system/sys@oldstyle_linux1 @param1 instance_name
NAME VALUE SES SYS ISMOD ISADJ
----------------------------------- --------------- ----- --------- ---------- -----
instance_name GREEN1 FALSE FALSE FALSE FALSE

[oracle@linux1 ~]$ cat oldstyl1 grep inet
16:40:02.555231 bind(6, {sa_family=AF_INET6, sin6_port=htons(0), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
16:40:02.666356 connect(9, {sa_family=AF_INET, sin_port=htons(1528), sin_addr=inet_addr("192.168.1.201")}, 16) = -1 EINPROGRESS (Operation now in progress)

For the remote node connection, it takes 6.5milliseconds.

[oracle@linux1 ~]$ strace -o oldstyl2 -af -tt sqlplus system/sys@oldstyle_linux1 @param1 instance_name

NAME VALUE SES SYS ISMOD ISADJ
----------------------------------- --------------- ----- --------- ---------- -----
instance_name GREEN2 FALSE FALSE FALSE FALSE

[oracle@linux1 ~]$ cat oldstyl2 grep inet
16:40:15.188398 connect(9, {sa_family=AF_INET, sin_port=htons(1528), sin_addr=inet_addr("192.168.1.201")}, 16) = -1 EINPROGRESS (Operation now in progress)
16:40:15.189370 getsockname(9, {sa_family=AF_INET, sin_port=htons(41163), sin_addr=inet_addr("192.168.1.201")}, [16]) = 0
16:40:15.194980 connect(9, {sa_family=AF_INET, sin_port=htons(1528), sin_addr=inet_addr("192.168.1.202")}, 16) = -1 EINPROGRESS (Operation now in progress).

It seems, while SCAN provides some advantages with node management at the cluster level, it seems, there is a connect-time penalty to every single connection even the connection ends up in the originating node.

2 comments:

Deepak Gupta Oracle DBA said...
This comment has been removed by the author.
Deepak Gupta Oracle DBA said...

Very informative posting.