Upload
ryota-watabe
View
685
Download
0
Embed Size (px)
Citation preview
なーんでだ?
2015-4-10 Oracle CloudWorld Tokyo Meetup! JPOUG
渡部 亮太
なーんでだ?
• アプリケーションからの接続テスト。 接続が成功したり失敗する奇妙な現象が発生 ! クライアントからDBサーバへのpingは成功するし、SQL*Plusでも接続は成功する…
ORA-12545
• 接続に失敗しました。ターゲット・ホストまたはオブジェクトが存在しません。
• 12c エラーメッセージガイド http://docs.oracle.com/cd/E57425_01/121/ERRMG/net12500.htm#sthref3644
"接続が成功したり失敗したり"
• どうやら半々の確率で成功するらしい
クライアントのtnsnames.ora
ORCL=(DESCRIPTION =
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP) (HOST=dbsvr1-vip) (PORT=1521) )
(ADDRESS=(PROTOCOL=TCP) (HOST=dbsvr2-vip) (PORT=1521) ) )
(CONNECT_DATA= (SERVICE_NAME=orcl.world ) )
)
# インスタンス テスト接続用
ORCL1=(DESCRIPTION =
(ADDRESS=(PROTOCOL=TCP) (HOST=dbsvr1-vip) (PORT=1521)
(CONNECT_DATA= (SERVICE_NAME=orcl.world )(INSTANCE_NAME=orcl1) )
)
ORCL2=(DESCRIPTION =
(ADDRESS=(PROTOCOL=TCP) (HOST=dbsvr2-vip) (PORT=1521)
(CONNECT_DATA= (SERVICE_NAME=orcl.world )(INSTANCE_NAME=orcl2) )
)
DBサーバへのアクセス可否
$ ping dbsvr1-vip # ==> OK
$ ping dbsvr2-vip # ==> OK
$ sqlplus system/password@ORCL1 # ==> OK
$ sqlplus system/password@ORCL2 # ==> OK
しかし・・・
アプリケーションからの接続(ネットサービス名ORCL使用)
# ==> 50%の確率でORA-12545
$ sqlplus system/password@ORCL
# ==> 50%の確率でORA-12545
(SCANを使用しない場合の) RACの接続の仕組みを
おさらいします
RACの接続の仕組み
SQL>
DBサーバ2
データベース
リスナー1
インスタンス 1
DBサーバ1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
①ローカルリスナーとリモートリスナーに自インスタンスの情報を登録(サービス登録)
リスナー1
データベース
インス1
インス2
リスナー2
データベース
インス1
インス2
※SCAN未使用
RACの接続の仕組み
SQL>
データベース
リスナー1
インスタンス 1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
②ADDRESS_LISTに複数指定されたリスナーのエンドポイント(VIP)から1つをランダムに選択し、接続リクエスト
③サーバサイドロードバランスが機能し、 インスタンス1,2のどちらに接続すべきか判断
※SCAN未使用
リスナー1
データベース
インス1
インス2
DBサーバ2 DBサーバ1
RACの接続の仕組み
SQL>
データベース
リスナー1
インスタンス 1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
※SCAN未使用
DBサーバ2 DBサーバ1
リスナーが インスタンス1に接続すべき と判断した場合
⑤ リスナー1がクライアントに インスタンス1への再送 (re-send)指示
④ リスナー1がインスタンス1へ接続を引き継ぎ
RACの接続の仕組み
SQL>
データベース
リスナー1
インスタンス 1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
※SCAN未使用
DBサーバ2 DBサーバ1
リスナーが インスタンス1に接続すべき と判断した場合
クライアントとインスタンス1で 仮想IPを使用して TCPセッションが確立される
⑦ インスタンス1へ接続要求
RACの接続の仕組み
SQL>
データベース
リスナー1
インスタンス 1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
※SCAN未使用
DBサーバ2 DBサーバ1
リスナーが インスタンス2に接続すべき と判断した場合
⑤ リスナー1がクライアントに インスタンス1へのリダイレクト 指示
RACの接続の仕組み
SQL>
データベース
リスナー1
インスタンス 1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
⑥リダイレクト指示に従い、 クライアントがDBサーバ2のVIPに接続リクエスト
⑧ リスナー2がクライアントに インスタンス2への再送 (re-send)指示
⑦ リスナー2がインスタンス2へ接続を引き継ぎ
※SCAN未使用
リスナー2
データベース
インス1
インス2
DBサーバ2 DBサーバ1
リスナーが インスタンス2に接続すべき と判断した場合
RACの接続の仕組み
SQL>
DBサーバ2
データベース
リスナー1
インスタンス 1
DBサーバ1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
⑨ インスタンス2へ接続要求
どのフェーズで ORA-12545が
発生しているか?
※SCAN未使用
リスナー2
データベース
インス1
インス2
クライアントとインスタンス2で 仮想IPを使用して TCPセッションが確立される
リスナーが インスタンス2に接続すべき と判断した場合
この環境のサービス登録状態 $ lsnrctl services
(略) Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
Services Summary...
Service "+ASM" has 1 instance(s).
(略)
Service "ocrl.world" has 2 instance(s).
Instance "ocrl1", status READY, has 2 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr1.domain)(PORT=1521))
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Instance "ocrl2", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr2.domain)(PORT=1521))
Service "ocrlXDB.world" has 2 instance(s).
(略)
The command completed successfully
リスナー1
orcl.world
orcl1
orcl2
"接続が成功したり失敗したり"
• どうやら半々の確率で成功するらしい
なーんでだ?
"接続が成功したり失敗したり"
• どうやら半々の確率で成功するらしい
• 確率的な動作?
• ロードバランスが関係する?
サーバサイドロードバランス
DBサーバ2
データベース
リスナー1
インスタンス 1
DBサーバ1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
リスナー1
データベース
インス1
インス2
リスナー2
データベース
インス1
インス2
REMOTE SERVERとして登録
(他ノードにインスタンスが存在する)
SQL> リスナー2に登録されているインスタンス1, 2のうち、インスタンスの負荷状態から接続先インスタンスを選択
Netトレース: ①接続要求 nscon: sending NSPTCN packet
(略)
nspsend: .. .. .. .. .. .. .. .. |......(D|
nspsend: .. .. .. .. .. .. .. .. |ESCRIPTI|
nspsend: .. .. .. .. .. .. .. .. |ON=(CONN|
nspsend: .. .. .. .. .. .. .. .. |ECT_DATA|
nspsend: .. .. .. .. .. .. .. .. |=(SERVER|
nspsend: .. .. .. .. .. .. .. .. |=DEDICAT|
nspsend: .. .. .. .. .. .. .. .. |ED)(SERV|
nspsend: .. .. .. .. .. .. .. .. |ICE_NAME|
nspsend: .. .. .. .. .. .. .. .. |=orcl.|
nspsend: .. .. .. .. .. .. .. .. |world)(C|
nspsend: .. .. .. .. .. .. .. .. |ID=(PROG|
nspsend: .. .. .. .. .. .. .. .. |RAM=sqlp|
nspsend: .. .. .. .. .. .. .. .. |lus)(HOS|
nspsend: .. .. .. .. .. .. .. .. |T=l63x64|
nspsend: .. .. .. .. .. .. .. .. |a.domain|
(略)
SQL>
dbsvr1
DB
dbsvr2
①
今回 説明の都合上Netトレースを若干修正しており、混乱を避けるため、16進ダンプ箇所を'..' と記載しています。
Netトレース: ②リダイレクト nscon: got NSPTRD packet
(略)
nsprecv: .. .. .. .. .. .. .. .. |.@(ADDRE|
nsprecv: .. .. .. .. .. .. .. .. |SS=(PROT|
nsprecv: .. .. .. .. .. .. .. .. |OCOL=TCP|
nsprecv: .. .. .. .. .. .. .. .. |)(HOST=d|
nsprecv: .. .. .. .. .. .. .. .. |dbsvr1.|
nsprecv: .. .. .. .. .. .. .. .. |domain)(|
nsprecv: .. .. .. .. .. .. .. .. |PORT=152|
nsprecv: .. .. .. .. .. .. .. .. |1)).(DES|
nsprecv: .. .. .. .. .. .. .. .. |CRIPTION|
nsprecv: .. .. .. .. .. .. .. .. |=(CONNEC|
nsprecv: .. .. .. .. .. .. .. .. |T_DATA=(|
nsprecv: .. .. .. .. .. .. .. .. |SERVER=D|
nsprecv: .. .. .. .. .. .. .. .. |EDICATED|
nsprecv: .. .. .. .. .. .. .. .. |)(SERVIC|
nsprecv: .. .. .. .. .. .. .. .. |E_NAME=o|
nsprecv: .. .. .. .. .. .. .. .. |rcl.wo|
nsprecv: .. .. .. .. .. .. .. .. |rld)(CID|
(略)
SQL>
dbsvr2
DB
dbsvr1
②
nsc2addr: entry
nsc2addr: (ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr2.domain)
(PORT=1521))
nttbnd2addr: entry
snlinGetAddrInfo: entry
snlinGetAddrInfo:
getaddrinfo() failed with error -2
snlinGetAddrInfo: exit
nttbnd2addr:
looking up IP addr for host: dbsvr2.domain
snlinGetAddrInfo: entry
snlinGetAddrInfo:
getaddrinfo() failed with error -3
snlinGetAddrInfo: exit
nttbnd2addr: *** hostname lookup failure! ***
nttbnd2addr: exit
nserror: entry
nserror: nsres: id=0, op=77, ns=12545, ns2=12560;
nt[0]=515, nt[1]=3, nt[2]=0; ora[0]=0, ora[1]=0,
ora[2]=0
Netトレース: ③接続(失敗)
SQL>
dbsvr2
DB
dbsvr1
③
ORA-12545の発生メカニズム
SQL>
dbsvr2
データベース
リスナー1
インスタンス 1
dbsvr1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
①DBサーバ1のVIP に、 接続リクエスト
ORA-12545
②DBサーバ1の物理IPのホスト名(“dbsvr2”)へ リダイレクト指示
192.168.xxx.xxx dbsvr1-vip
192.168.xxx.xxx dbsvr2-vip
クライアントのhostsファイル
SQL>
データベース
リスナー1
インスタンス 1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
DBサーバ2 DBサーバ1
必要最小限という考えから仮想VIPのみをhostsファイルに登録
サービス登録の状態 $ lsnrctl services
(略) Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
Services Summary...
Service "+ASM" has 1 instance(s).
(略)
Service "ocrl.world" has 2 instance(s).
Instance "ocrl1", status READY, has 2 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr1.domain)(PORT=1521))
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Instance "ocrl2", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr2.domain)(PORT=1521))
Service "ocrlXDB.world" has 2 instance(s).
(略)
The command completed successfully
リスナー1
orcl.world
orcl1
orcl2
あれれ?VIPじゃない・・
あれれ?VIPじゃない・・
LOCAL_LISTENER
【誤】
(ADDRESS=(PROTOCOL=TCP)
(HOST=dbsvr1.domain)(PORT=1521))
【正】
(ADDRESS=(PROTOCOL=TCP)
(HOST=dbsvr1-vip.domain)(PORT=1521))
サービス登録の状態 $ lsnrctl services
(略) Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
Services Summary...
Service "+ASM" has 1 instance(s).
(略)
Service "ocrl.world" has 2 instance(s).
Instance "ocrl1", status READY, has 2 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr1-vip.domain)(PORT=1521))
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Instance "ocrl2", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=dbsvr2-vip.domain)(PORT=1521))
Service "ocrlXDB.world" has 2 instance(s).
(略)
The command completed successfully
リスナー1
orcl.world
orcl1
orcl2
本来はVIPであるべき
本来はVIPであるべき
ORA-12545の発生メカニズム
SQL>
dbsvr2
データベース
リスナー1
インスタンス 1
dbsvr1
VIP 物理IP
リスナー2
インスタンス 2
VIP 物理IP
①DBサーバ1のVIP に、 接続リクエスト
ORA-12545
②DBサーバ1の物理IPのホスト名(“dbsvr2”)へ リダイレクト指示
正しくは仮想VIP(“dbsvr2-vip”)へリダイレクトされるべき
クライアントの/etc/hosts
192.168.xxx.xxx dbsvr1-vip
192.168.xxx.xxx dbsvr2-vip
必要最小限という考えから仮想VIPのみをhostsファイルに登録
[原因] LOCAL_LISTENERの設定ミス (+ クライアントの名前解決設定)
「悪い」設定というわけではない。 LOCAL_LISTENERの設定が正しければ問題にはならない。 今回は裏目に出ただけ
補足
• 11.2 Grid Infrastructureにはリスナーの動的構成機能があり、これを利用するとLOCAL_LISTENERが適切にVIPに設定され、今回の問題は発生しない
• 今回は手動でLOCAL_LISTENERを誤って設定したため問題が発生した
おしまい