30
なーんでだ? 2015-4-10 Oracle CloudWorld Tokyo Meetup! JPOUG 渡部 亮太

なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

Embed Size (px)

Citation preview

Page 1: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

なーんでだ?

2015-4-10 Oracle CloudWorld Tokyo Meetup! JPOUG

渡部 亮太

Page 2: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

なーんでだ?

• アプリケーションからの接続テスト。 接続が成功したり失敗する奇妙な現象が発生 ! クライアントからDBサーバへのpingは成功するし、SQL*Plusでも接続は成功する…

Page 3: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

ORA-12545

• 接続に失敗しました。ターゲット・ホストまたはオブジェクトが存在しません。

• 12c エラーメッセージガイド http://docs.oracle.com/cd/E57425_01/121/ERRMG/net12500.htm#sthref3644

Page 4: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

"接続が成功したり失敗したり"

• どうやら半々の確率で成功するらしい

Page 5: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

クライアントの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) )

)

Page 6: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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

Page 7: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

(SCANを使用しない場合の) RACの接続の仕組みを

おさらいします

Page 8: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

RACの接続の仕組み

SQL>

DBサーバ2

データベース

リスナー1

インスタンス 1

DBサーバ1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

①ローカルリスナーとリモートリスナーに自インスタンスの情報を登録(サービス登録)

リスナー1

データベース

インス1

インス2

リスナー2

データベース

インス1

インス2

※SCAN未使用

Page 9: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

RACの接続の仕組み

SQL>

データベース

リスナー1

インスタンス 1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

②ADDRESS_LISTに複数指定されたリスナーのエンドポイント(VIP)から1つをランダムに選択し、接続リクエスト

③サーバサイドロードバランスが機能し、 インスタンス1,2のどちらに接続すべきか判断

※SCAN未使用

リスナー1

データベース

インス1

インス2

DBサーバ2 DBサーバ1

Page 10: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

RACの接続の仕組み

SQL>

データベース

リスナー1

インスタンス 1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

※SCAN未使用

DBサーバ2 DBサーバ1

リスナーが インスタンス1に接続すべき と判断した場合

⑤ リスナー1がクライアントに インスタンス1への再送 (re-send)指示

④ リスナー1がインスタンス1へ接続を引き継ぎ

Page 11: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

RACの接続の仕組み

SQL>

データベース

リスナー1

インスタンス 1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

※SCAN未使用

DBサーバ2 DBサーバ1

リスナーが インスタンス1に接続すべき と判断した場合

クライアントとインスタンス1で 仮想IPを使用して TCPセッションが確立される

⑦ インスタンス1へ接続要求

Page 12: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

RACの接続の仕組み

SQL>

データベース

リスナー1

インスタンス 1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

※SCAN未使用

DBサーバ2 DBサーバ1

リスナーが インスタンス2に接続すべき と判断した場合

⑤ リスナー1がクライアントに インスタンス1へのリダイレクト 指示

Page 13: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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に接続すべき と判断した場合

Page 14: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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に接続すべき と判断した場合

Page 15: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

この環境のサービス登録状態 $ 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

Page 16: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

"接続が成功したり失敗したり"

• どうやら半々の確率で成功するらしい

Page 17: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

なーんでだ?

Page 18: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

"接続が成功したり失敗したり"

• どうやら半々の確率で成功するらしい

• 確率的な動作?

• ロードバランスが関係する?

Page 19: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

サーバサイドロードバランス

DBサーバ2

データベース

リスナー1

インスタンス 1

DBサーバ1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

リスナー1

データベース

インス1

インス2

リスナー2

データベース

インス1

インス2

REMOTE SERVERとして登録

(他ノードにインスタンスが存在する)

SQL> リスナー2に登録されているインスタンス1, 2のうち、インスタンスの負荷状態から接続先インスタンスを選択

Page 20: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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進ダンプ箇所を'..' と記載しています。

Page 21: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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

Page 22: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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

Page 23: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

ORA-12545の発生メカニズム

SQL>

dbsvr2

データベース

リスナー1

インスタンス 1

dbsvr1

VIP 物理IP

リスナー2

インスタンス 2

VIP 物理IP

①DBサーバ1のVIP に、 接続リクエスト

ORA-12545

②DBサーバ1の物理IPのホスト名(“dbsvr2”)へ リダイレクト指示

Page 24: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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ファイルに登録

Page 25: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

サービス登録の状態 $ 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じゃない・・

Page 26: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

LOCAL_LISTENER

【誤】

(ADDRESS=(PROTOCOL=TCP)

(HOST=dbsvr1.domain)(PORT=1521))

【正】

(ADDRESS=(PROTOCOL=TCP)

(HOST=dbsvr1-vip.domain)(PORT=1521))

Page 27: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

サービス登録の状態 $ 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であるべき

Page 28: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

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の設定が正しければ問題にはならない。 今回は裏目に出ただけ

Page 29: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

補足

• 11.2 Grid Infrastructureにはリスナーの動的構成機能があり、これを利用するとLOCAL_LISTENERが適切にVIPに設定され、今回の問題は発生しない

• 今回は手動でLOCAL_LISTENERを誤って設定したため問題が発生した

Page 30: なーんでだ? Meetup! JPOUG @ 2015-04-10 Oracle CloudWorld

おしまい