クライアントの物理接続に対して、ODPは自身とバックエンドの複数のOBServerノード間の接続を維持し、バージョン番号に基づく増分同期方式を用いて各OBServerノードの接続を同一状態に保つことで、クライアントが各OBServerノードに効率的にアクセスできるようにします。接続管理のもう一つの機能は接続保持であり、OBServerノードがダウンしたり、アップグレードされたり、再起動したりした場合でも、クライアントとODPとの接続は切断されません。ODPは健全なOBServerノードへ迅速に切り替えることができ、アプリケーションには透過的です。
接続の作成
ODPのセッションは、Client SessionとServer Sessionの2種類に分類されます。Client Sessionとは、クライアントとODPの間に確立される接続を指します。Server Sessionとは、ODPとOBServerノードの間に作成される接続を指します。ODPがOBServerノードにクライアントのリクエストを転送する際、OBServerノードとの間に接続が作成されていない場合は、セッションインスタンスを初期化する必要があります。
セッションの作成時には認証操作が必要です。ODPはそのセッションが将来どのOBServerにアクセスするかを決定できないため、認証プロセスでは、ODPは任意のOBServerノードを選択して認証を行い、クライアントから送信された認証データパケットをそのOBServerノードに転送し、OBServerノードから返された結果をクライアントに転送します。同時に、クライアントの認証データパケットはすべてClient Session内部にキャッシュされ、ODPが他のOBServerノードとそのClient Session関連のServer Sessionを確立する際に、これらの認証データパケットをOBServerノードに送信し、OBServerノードとの円滑な認証を実現します。
接続の保存
クライアントがODPにリクエストを送信するたびに、クライアント接続情報に基づいてClient Sessionを取得する必要があります。非接続プールモードでは、Server SessionはClient Sessionなしに独立して存在することはできず、Client Sessionに基づいて関連するServer Sessionを照会するか、特定のServer Sessionが特定のClient Sessionと関連付けられているかどうかを照会する必要があります。
ODPがクライアントのSQLリクエストを受信すると、partition table cacheを照会してOBServerノードのアドレスを取得し、次にClient Sessionに保存されているServer SessionにそのOBServerノードに関連付けられたServer Sessionが存在するかどうかを照会します。存在する場合はそのServer Sessionを使用し、存在しない場合はそのOBServerノードに接続を作成し、Server SessionをClient Session関連のServer Session保存構造に追加します。
トランザクション状態の維持
デフォルト設定または非分散トランザクションモードでは、ODPはトランザクションに基づいてClient SessionとServer Sessionをバインドします。トランザクションの最初のステートメントがODPに到達すると、ODPは1つのServer Sessionを選択してClient Sessionにバインドし、その後のトランザクション内のすべてのリクエストはこのServer Sessionを通じてOBServerに転送されます。Server Sessionの切り替えは禁止されています。したがって、ODPはClient Session内にトランザクション状態を記録し、バインド関係を維持する必要があります。
非分散トランザクションモードでは、トランザクション状態を維持する主な目的は、トランザクション中にServer Sessionを切り替えないことを保証することです。 具体的には:
トランザクション中にOBServerがダウンした場合、ODPはノードの状態を検出し、未完了のトランザクションを終了させる必要があります。MySQLプロトコルにはタイムアウトメカニズムがないため、ODPはクライアントに対してトランザクションの終了を積極的に通知する必要があります。
OBServerノードがトランザクションの同期を実装していないため、トランザクションの移行機能は現在サポートされていません。トランザクションは初期のOBServerでのみ処理でき、ノードの切り替えは失敗につながります。そのため、ODPがプライマリ/スタンバイ切り替えを行う際には、進行中のトランザクションを完了させるか、特別なエラーを返してクライアントにトランザクションの終了を通知する必要があります。
もう一つの目的は、ODPのアップグレード時に、古いODPをKillしてサービスを停止する前に、すべてのトランザクションが完了するのを待ち、ユーザーへの影響を最小限に抑えることです。
分散トランザクションルーティングが有効な場合(パラメータenable_ob_protocol_v2=trueおよびenable_transaction_internal_routing=trueの設定)、トランザクション内でServer Sessionの切り替えが許可されます。 このモードでは、ODPはSQLが関わるパーティションの位置に基づいて最適なOBServerノードを動的に選択し、トランザクション内でのノード間ルーティングを実現します。この場合、トランザクション状態の維持の目的は、ルーティングの一貫性と障害回復を保証することに移ります。ODPは依然としてノードのダウンやプライマリ/スタンバイ切り替えを処理するためにトランザクション状態を記録する必要がありますが、ノード間ルーティングをサポートするため、トランザクション移行の制限が部分的に緩和され、ODPは内部メカニズムを通じて複数ノードのトランザクションを調整できます。
トランザクション開始時には、トランザクションの開始状態をClient Sessionに記録し、トランザクション終了時にはそのトランザクション状態をリセットします。トランザクション終了の判断基準は以下の通りです:
Autocommitを使用している場合、各リクエストごとにOBServerからの応答パケットを解析し、データ転送完了後に即座にトランザクション状態をリセットします。
長時間トランザクションの場合、Commit/Rollbackリクエスト後に応答パケットを解析してトランザクション終了を判断します。
接続変数の管理
Client Sessionは、そのセッション上でクライアントが設定したすべての変数を記録する必要があります。変数を変更するたびに、Client Sessionに変更日時を記録します。ODPがServer Sessionを選択してリクエストを転送する際、まずそのServer Session上のSession変数の変更日時がClient Sessionに記録された変更日時より新しいかどうかをチェックします。新しい場合、そのSessionが最新のSession変数を使用していないことを意味します。ODPはまずそのServer Session上のすべてのSession変数をリセットし、現在のClient Sessionに保存されているSession変数を一括してそのServer Sessionに設定した後、そのServer Sessionを通じてリクエストを転送します。そうでない場合は、直接そのServer Sessionを通じて転送します。
autocommitなどの一般的なSession変数については、クライアントが頻繁に設定を変更する可能性があるため、modify timeに基づいて一括リセットを行うかどうかを判断することはできません。代わりに、各Server Sessionはこれら一般的なSession変数の値を保存し、リクエストごとにClient Sessionの変数値とServer Sessionの変数値が一致するかどうかを比較します。一致しない場合は、これらの変数値を再設定します。
フラッシュダウンの回避
フラッシュダウンの回避とは、ODPとOBServerノード間のサーバーセッション異常がクライアントに感知されないことを指します。クライアントとODP間のクライアントセッションは正常であり、クライアントは正常にデータの読み書きができます。サーバーセッション異常を処理する必要があるケースは以下のとおりです:
OBServerノードでリーダー切り替えが発生し、ODPが新しいリーダーを取得していない場合。この状況は主にOBServerノードが処理します。リーダー切り替えでは、処理中のトランザクションをすべて完了させる必要があります。ODPは、リクエストをデータが存在するOBServerノードに送信するよう努めます。OBServerノードでリーダー切り替えが発生した場合、データがそのOBServerノード上になくても、そのノードはそのリクエストを処理し、結果をODPに返す責任があります。
OBServerノードがダウンした場合、ODPとそのOBServerノードとの接続が切断されます。そのサーバーセッションがトランザクションを処理中の場合、ODPはクライアントにエラーレスポンスを送信する必要があります。そのサーバーセッションがアイドル状態の場合は、そのサーバーセッションを対応するクライアントセッションからマークして削除するだけで済みます。新しいリクエストは、そのサーバーセッションを使用して転送されません。
ODPとOBServerノード間の通信がタイムアウトした場合。MySQLプロトコル自体にはタイムアウトメカニズムがありませんが、OBServerノードにはタイムアウトメカニズムがあります。そのため、OBServerノードがタイムアウトするとODPに通知され、ODPがクライアントにエラー通知を送信します。OBServerノードがサーバーセッションが長時間アクティブでないことを検出した場合も、そのセッションをKillします。この場合の処理は、項目2の処理方法を参照してください。
ODPとOBServerノード間のネットワーク接続が切断されたり、ネットワークパーティションが発生したりした場合。この場合の処理は、項目2を参照してください。ネットワークパーティションが発生しても、サーバーセッション上でトランザクションが実行中の場合、OBServerは一定時間後にそのセッションを終了します。そのため、ODPはサーバーセッションが切断されて一定時間経過した後、クライアントにエラーを報告し、未完了のトランザクションを終了させることで、セッションが長時間ハングアップするのを防ぎます。
ODPのアップグレード。新しく起動したODPがクライアントから開始された新しいセッションを担当し、古いODP上のセッション数はどんどん少なくなります。古いODP上のセッション数が特定のしきい値を下回った場合、古いODP上のすべてのセッションを終了させる必要があります(もちろん、処理中のトランザクションを完了させる必要があります。長時間のトランザクションはしばらく待機する必要があり、タイムアウトしても完了しない場合は強制的にKillするしかありません)。その後、古いODPを停止します。このプロセスでは、クライアント接続のフラッシュダウンを完全に避けることはできません。
ODPがダウンした場合。この場合、ODP上のすべての接続が切断されます。ODPはすぐに再起動するかもしれませんし、そのODPが担当していた接続が他のODPによって処理されるかもしれません。フラッシュダウンは避けられません。
ODPを使用することで、ほとんどの異常状況下での接続フラッシュダウンを回避できます。特に、OBServerノードでのリーダー切り替え、プライマリ/スタンバイクラスタ切り替え、ODPのアップグレードなどのバックエンドメンテナンス後は、クライアント接続を正常に維持でき、クライアントへの影響は比較的小さいです。
セッションKill処理
MySQLプロトコルにはタイムアウトメカニズムがありませんが、MySQLは長時間アクティブでないセッションをKillします。クライアントがサーバー側の応答を待ち続ける場合、このようなハングアップ状態が発生します。このような場合、一般的にDBAが介入し、MySQLのKill Sessionコマンドを呼び出してセッションを閉じます。
OBServerノードにはタイムアウトメカニズムがあります。通常、サーバー側のダウン、ネットワークパーティション、またはobproxyとサーバー側との接続が切断された場合でも、obproxyはクライアントセッションにトランザクション処理失敗を通知できます。しかし、タイムアウト時間が長すぎる設定になっているか、obproxyの処理に漏れがあり、クライアントセッションが実際にハングアップしてしまった場合、アプリケーションはKill Session操作を要求します。obproxyはKill Sessionを特別に処理できる必要があり、obproxy上に記録されたクライアントセッションの状態を処理するだけでなく、OBServerに通知してサーバーセッションを閉じさせる必要があります。