Db2 HADRの「テイクオーバーが失敗する・終わらない」を切り分ける ― SQL1770Nの理由コードとログギャップ
HADRのテイクオーバーを試したら SQL1770N で失敗する。あるいは応答がなかなか返ってこない——。「HADRの構成が悪いのか」「切り替え運用は信用できない」と考えてしまいがちですが、テイクオーバーの失敗は理由コードとHADRの状態を見れば機械的に切り分けられます。
この記事では、SQL1770N の代表的な理由コード、計画切替(通常テイクオーバー)と緊急切替(BY FORCE)の使い分け、そして「そもそもテイクオーバーできる状態か」を事前に判断するための peer状態・ログギャップ の見方を、実機での再現ログとともに整理します。
検証環境は2ノードHADR(db2node1=プライマリ / db2node2=スタンバイ、Db2 12.1.4 / NEARSYNC)です。
まず結論:失敗したら「理由コード」と「peer状態」を見る
テイクオーバーには2種類あります。
-
計画切替(通常):
TAKEOVER HADR ON DATABASE <db>をスタンバイ側で実行。peer状態が前提で、ロールを入れ替える。 -
緊急切替:
TAKEOVER ... BY FORCE。プライマリ障害時に、peerでなくてもスタンバイを昇格できる。ただしデータロストのリスクがある。
失敗したときは、メッセージの理由コードを見ます。
SQL1770N Takeover HADR cannot complete. Reason code = "N".
実機でよく出るのは次の2つです。
| 理由コード | 状況 | 対処 |
|---|---|---|
| 4 | プライマリ側で通常テイクオーバーを実行した(撃つノードの間違い) | スタンバイ側で実行する |
| 1 | スタンバイがpeer状態でない(プライマリ不達・カタチアップ中など) | 状態を確認。プライマリ障害なら BY FORCE
|
以下、この2つと緊急切替を実機で再現します。
テイクオーバー前に必ず見る:peer状態とログギャップ
計画切替は「スタンバイがプライマリに追いついていて(peer)、接続している」ことが前提です。切り替える前に必ず確認します。
# ロールと状態を一発で確認
db2pd -db SAMPLE -hadr
-- peer状態・接続・ログギャップをまとめて確認
SELECT HADR_STATE, HADR_CONNECT_STATUS, HADR_LOG_GAP,
LOG_HADR_WAIT_TIME, HADR_SYNCMODE
FROM TABLE(MON_GET_HADR(NULL)) AS T;
健全なら次のように見えます。
HADR_STATE HADR_CONNECT_STATUS HADR_LOG_GAP LOG_HADR_WAIT_TIME HADR_SYNCMODE
----------- ------------------- ------------ ------------------ -------------
PEER CONNECTED 0 6 NEARSYNC
-
HADR_STATE = PEERかつHADR_CONNECT_STATUS = CONNECTED… 計画切替が可能な状態。 -
HADR_LOG_GAP(バイト)… プライマリとスタンバイのログ差。大きいほどスタンバイが遅れている。切り替え直後の性能や、BY FORCE時のデータロスト量に直結する。 -
LOG_HADR_WAIT_TIME(ミリ秒)が増え続けるなら、CPUやメモリより先にネットワーク帯域を疑う。
HADR_STATE が PEER 以外(REMOTE_CATCHUP など)のときに計画切替を撃つと、後述の理由コード1で弾かれます。
失敗例①:撃つノードを間違える(プライマリで通常テイクオーバー)
通常テイクオーバーはスタンバイ側で実行します。プライマリ側で撃つと失敗します。
# db2node1(プライマリ)で誤って実行
db2 "TAKEOVER HADR ON DATABASE SAMPLE"
SQL1770N Takeover HADR cannot complete. Reason code = "4".
理由コード4は「このデータベースは既にプライマリ」という意味です。撃った後もロールは変わりません(HADR_ROLE = PRIMARY / HADR_STATE = PEER のまま)。害はないが1歩も進まないので、慌てているときほど「どのノードで実行しているか」を先に確認します。
失敗例②:peer状態でないのに通常テイクオーバー(プライマリ障害)
プライマリが落ちた状況を実機で作って再現します。まずプライマリを停止します。
# db2node1(プライマリ)を停止して障害を模擬
db2stop force
このときスタンバイ(db2node2)から状態を見ると、peerが崩れています。
db2pd -db SAMPLE -hadr
HADR_ROLE = STANDBY
HADR_STATE = REMOTE_CATCHUP_PENDING
HADR_CONNECT_STATUS = DISCONNECTED
この状態で通常テイクオーバーを撃つと、理由コード1で失敗します。
# db2node2(スタンバイ)で通常テイクオーバーを試みる
db2 "TAKEOVER HADR ON DATABASE SAMPLE"
SQL1770N Takeover HADR cannot complete. Reason code = "1".
理由コード1は「スタンバイがpeer状態でないため、計画切替はできない」という意味です。プライマリが生きていれば「まず追いつかせる(peerに戻す)」のが筋ですが、プライマリが本当に落ちているなら、次の緊急切替に進みます。
緊急時:BY FORCE で昇格する(データロストに注意)
プライマリが復旧しない障害では、BY FORCE でスタンバイを強制昇格します。
# db2node2(スタンバイ)で緊急テイクオーバー
db2 "TAKEOVER HADR ON DATABASE SAMPLE BY FORCE"
DB20000I The TAKEOVER HADR ON DATABASE command completed successfully.
昇格後の状態です。旧プライマリが不在なので DISCONNECTED ですが、新プライマリとして接続を受け付けられるようになります。
HADR_ROLE = PRIMARY
HADR_STATE = DISCONNECTED
HADR_CONNECT_STATUS = DISCONNECTED
→ 新プライマリ(db2node2)へ接続 OK。業務を再開できる。
BY FORCE の後始末:旧プライマリをスタンバイに戻す
BY FORCE の後は、旧プライマリを新プライマリのスタンバイとして再統合します。旧プライマリを起動し、スタンバイとして起動し直します。
# 旧プライマリ db2node1 で
db2start
db2 "START HADR ON DATABASE SAMPLE AS STANDBY"
SQL1063N DB2START processing was successful.
DB20000I The START HADR ON DATABASE command completed successfully.
→ db2node1: HADR_ROLE=STANDBY / HADR_STATE=PEER / CONNECTED
→ db2node2: HADR_ROLE=PRIMARY / HADR_STATE=PEER / CONNECTED
今回は切り替え時のログギャップが0だったため、スタンバイとしてそのまま PEER に復帰できました。
計画切替は健全なpeerで(正常系の確認)
比較のために、健全なpeer状態での計画切替も載せます。スタンバイ側で実行すると、ロールが入れ替わります。
# 昇格させたい側(現スタンバイ)で実行
db2 "TAKEOVER HADR ON DATABASE SAMPLE"
DB20000I The TAKEOVER HADR ON DATABASE command completed successfully.
→ 実行した側: HADR_ROLE=PRIMARY / HADR_STATE=PEER
→ 相手側 : HADR_ROLE=STANDBY / HADR_STATE=PEER
計画メンテナンスでの切り替えはこれで済みます。失敗するのは「peerでない」か「撃つノードが違う」かのどちらかです。
テイクオーバーが失敗したときのチェックリスト
- メッセージの理由コードを見る(
SQL1770N ... Reason code = "N") -
4なら撃つノードが違う。スタンバイ側で実行し直す -
1ならpeer状態でない。db2pd -hadrでHADR_STATEとHADR_CONNECT_STATUSを確認 - プライマリが生きているなら、まず追いつかせて
PEERに戻す(ネットワーク/ログギャップを確認) - プライマリが本当に落ちているなら、
HADR_LOG_GAPを確認のうえBY FORCE -
BY FORCE後は旧プライマリをスタンバイとして再統合(分岐していたら作り直す)
補足:テイクオーバー後、アプリ側で SQL30108N が出るのは正常
テイクオーバーが成功すると、ACR(自動クライアントリルート)を設定したアプリには SQL30108N が返ります。これはエラーではなく「新プライマリへ再接続した」通知です。ここをエラー扱いすると、切り替えは成功しているのにアプリが止まります。アプリ側の扱いは別記事にまとめました。
📕 もっと深く:Db2運用を12章で体系化した本を書きました
この記事で扱ったテイクオーバーの切り分けは、HADR運用の一部です。
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ——そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にしました。実機で検証した内容と、Db2の設計上そうなる理由をまとめました。
アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR(本記事の深掘り版:構築・状態確認・テイクオーバー・pureScale+HADRの落とし穴・ACR)/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集まで、全12章+運用シェルスクリプト集です。
HADRの切り替えで踏んだ地雷や、扱ってほしいテーマがあれば、ぜひコメントで教えてください。次の記事のネタにさせてもらいます。
Discussion