今回は静的リスナー構成をしているとハマりがちな現象を備忘録として残す。

概要


オラクルにはリスナー経由での接続方式があり、そのリスナーの構成は動的構成、静的構成の二種類がある。 静的リスナー構成の場合、リスナーはデータベースの状態を把握していない。 この場合の不都合な点は、本来データベースが停止していてフェイルオーバーしてほしいのに、 リスナーがデータベースの状態を把握していないがために フェイルオーバーがされないといった事態が起きてしまう点である。 たとえば、ネットサービス名にFAILOVERの記述をしてあったとしても、接続先のリスナーが静的構成をされていて サービスを受け付けている場合は、データベースが実際には停止していてもtnspingなどではOKが出るため(リスナーはサービスを認識しているため)、FAILOVERがされない。それを備忘録として残しておく。

環境


oracle 12c ( Single Instance )
今回はシングルインスタンスのデータガード構成とする(スタンバイはフィジカルスタンバイ)。

ホストの情報

information プライマリ スタンバイ
hostname test1 test2
IP 192.168.56.109 192.168.56.110

DBの情報

DB_NAME : testdb

parameter プライマリ スタンバイ
DB_UNIQUE_NAME testdb stestdb
ORACLE_SID testdb stestdb

リスナー

静的リスナー構成 ( サービスteeestを受け付ける )
ポート番号:1521

1. 静的リスナー構成


listener.oraにて以下のように記述し静的リスナー構成にする。

# プライマリ側 ( host : test1 )

oracle@test1$ cd $ORACLE_HOME/network/admin

oracle@test1$ test -e listener.ora && cp -p listener.ora listener.ora.$(/bin/date +"%Y%m%d")

oracle@test1$ cat <<'EOF' > listener.ora
LISTENER=
  (DESCRIPTION=
    (ADDRESS_LIST=
      (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.109)(PORT=1521))
    )
  )

SID_LIST_LISTENER =
  (SID_DESC=
    (GLOBAL_DBNAME=teeest)
    (SID_NAME=testdb)
      (ORACLE_HOME=/u01/app/oracle/product/12.1.0/dbhome)
    )

# スタンバイ側 ( host : test2 )

oracle@test2$ cd $ORACLE_HOME/network/admin

oracle@test2$ test -e listener.ora && cp -p listener.ora listener.ora.$(/bin/date +"%Y%m%d")

oracle@test2$ cat <<'EOF' > listener.ora
LISTENER=
  (DESCRIPTION=
    (ADDRESS_LIST=
      (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.110)(PORT=1521))
    )
  )

SID_LIST_LISTENER =
  (SID_DESC=
    (GLOBAL_DBNAME=teeest)
    (SID_NAME=stestdb)
      (ORACLE_HOME=/u01/app/oracle/product/12.1.0/dbhome)
    )

EOF

2. 実験用ネットサービス名の作成


tnsnames.oraを作成する。

# プライマリ側 ( host : test1 )

oracle@test2$ cd $ORACLE_HOME/network/admin

oracle@test2$ test -e tnsnames.ora && cp -p tnsnames.ora tnsnames.ora.$(/bin/date +"%Y%m%d")

# 実験のためスタンバイ側を最初の接続先として記述する

oracle@test2$ cat <<'EOF' >> tnsnames.ora
hogehoge=
 (DESCRIPTION=
  (FAILOVER=on)
  (ADDRESS=(PROTOCOL=tcp)(HOST=test2)(PORT=1521))
  (ADDRESS=(PROTOCOL=tcp)(HOST=test1)(PORT=1521))
  (CONNECT_DATA=(SERVICE_NAME=teeest))
  )
EOF

さて、これにて準備完了。

3. 舞台を整える


下準備完了したので、以下の手順を実施し通常時の状態をつくる。

  1. DBの起動(プライマリ、スタンバイ側両方)
  2. リスナーの起動(プライマリ、スタンバイ側両方)
  3. 接続の確認

DBの起動

[oracle@test2 ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on 月 6月 4 22:11:03 2018

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

アイドル・インスタンスに接続しました。

SQL> startup;
ORACLEインスタンスが起動しました。

Total System Global Area 1660944384 bytes
Fixed Size		    2925072 bytes
Variable Size		 1056968176 bytes
Database Buffers	  587202560 bytes
Redo Buffers		   13848576 bytes
データベースがマウントされました。
データベースがオープンされました。
SQL>

リスナーの起動

[oracle@test2 admin]$ lsnrctl start

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 04-6月 -2018 22:13:08

Copyright (c) 1991, 2014, Oracle.  All rights reserved.

/u01/app/oracle/product/12.1.0/dbhome/bin/tnslsnrを起動しています。お待ちください...

TNSLSNR for Linux: Version 12.1.0.2.0 - Production
システム・パラメータ・ファイルは/u01/app/oracle/product/12.1.0/dbhome/network/admin/listener.oraです。
ログ・メッセージを/u01/app/oracle/diag/tnslsnr/test2/listener/alert/log.xmlに書き込みました。
リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.110)(PORT=1521)))

(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.110)(PORT=1521)))に接続中
リスナーのステータス
------------------------
別名                      LISTENER
バージョン                TNSLSNR for Linux: Version 12.1.0.2.0 - Production
開始日                    04-6月 -2018 22:13:08
稼働時間                  0 日 0 時間 0 分 0 秒
トレース・レベル          off
セキュリティ              ON: Local OS Authentication
SNMP                      OFF
パラメータ・ファイル      /u01/app/oracle/product/12.1.0/dbhome/network/admin/listener.ora
ログ・ファイル            /u01/app/oracle/diag/tnslsnr/test2/listener/alert/log.xml
リスニング・エンドポイントのサマリー...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.110)(PORT=1521)))
サービスのサマリー...
サービス"teeest"には、1件のインスタンスがあります。
  インスタンス"stestdb"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
コマンドは正常に終了しました。
[oracle@test2 admin]$

ちなみに静的リスナー構成の場合は、リスナーはインスタンス(データベース)の状態を把握していないため 状態UNKNOWNと表示されるので、これで静的リスナー構成であることを確認できる。

プライマリ側も同様にDB、リスナーを起動する。

接続の確認

プライマリ、スタンバイ、両方のデータベース、リスナーを起動したところで
まずはDBへの接続が問題ないことを確認する。

[oracle@test1 admin]$ tnsping hogehoge

TNS Ping Utility for Linux: Version 12.1.0.2.0 - Production on 04-6月 -2018 22:17:51

Copyright (c) 1997, 2014, Oracle.  All rights reserved.

パラメータ・ファイルを使用しました:


エイリアスを解決するためにTNSNAMESアダプタを使用しました。
(DESCRIPTION= (FAILOVER=on) (ADDRESS=(PROTOCOL=tcp)(HOST=test2)(PORT=1521)) (ADDRESS=(PROTOCOL=tcp)(HOST=test1)(PORT=1521)) (CONNECT_DATA=(SERVICE_NAME=teeest)))に接続の試行中
OK (10ミリ秒)
[oracle@test1 admin]$ sqlplus testuser/testuser@hogehoge

SQL*Plus: Release 12.1.0.2.0 Production on 月 6月 4 22:18:11 2018

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

最終正常ログイン時間: 火 5月  22 2018 22:39:29 +09:00


Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
------------------------------------------------
stestdb

4. フェイルオーバーに失敗するケースの確認


いよいよ確認に入る。 まずはスタンバイデータベースを停止する。

SQL> shutdown immediate;
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SQL>

では、再度接続を試す。

[oracle@test1 admin]$ sqlplus testuser/testuser@hogehoge

SQL*Plus: Release 12.1.0.2.0 Production on 月 6月 4 22:22:04 2018

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

ERROR:
ORA-01034: ORACLE not available
ORA-27101: shared memory realm does not exist
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3640
Additional information: 225813055
プロセスID: 0
セッションID: 0、シリアル番号: 0


ユーザー名を入力してください:

エラーが起きて接続に失敗した。 念のために簡易接続ネーミングを利用した接続にてプライマリDBには問題なく接続できることを確認する。

[oracle@test1 admin]$ sqlplus testuser/testuser@test1:1521/teeest

SQL*Plus: Release 12.1.0.2.0 Production on 月 6月 4 22:23:31 2018

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

最終正常ログイン時間: 火 5月  22 2018 22:39:29 +09:00


Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
------------------------------------------------
testdb

SQL>

このことから、ネットサービス名hogehogeで記載しているtestdbへのFAILOVERがされていないことがわかる。

これは一重に、静的リスナー構成をしているために起こる現象である。 接続先リスナーがサービスを認識しているがためFAILOVERは発動されず ただ、実際にはインスタンス(データベース)は停止しているためエラーを返す。

最後に


データガード構成の際、特にRAC構成の場合、 スタンバイDB構築の際にRMANを用いてプライマリDBからduplicateを実施するために 一時的にASM側のリスナーを静的構成にして起動する必要があるが
スタンバイDB構築後もこのリスナーを静的構成のままにしていたりすると
プライマリ、スタンバイ側で起動しているインスタンスのノードや数の違いによっては スイッチオーバーのテストの際など、FAILOVER句が発動されず頭を抱えることになる。
FAILOVERがされないときは静的リスナー構成になっていないか確認すると良い。