アクセスが集中する時間帯や、大量のバッチが一斉に走るタイミングで、こんなエラーが返ってくることがあります。
SQL1224N The database manager is not able to accept new requests,
has terminated all requests in progress, or has terminated the
specified request because of an error. SQLSTATE=55032
SQL1224N ―― メッセージは抽象的ですが、実体は「接続を捌くためのエージェント(プロセス)を起動できなかった、または起動済みのものが切られた」という状態です。Db2 12.1 の実機で確かめると、SQL1224N が返ったのはすでに張ってあるローカル(IPC)接続が強制的に切られ、その接続で次の要求を投げたときでした。同じ操作でも TCP/IP 接続では SQL30081N(recv)、代替サーバーを設定していれば SQL30108N が返ります。Db2に到達したかどうかではなく、接続経路(ローカルIPCか TCP/IP か)で返るコードが変わる、と捉えてください。
原因の多くは、次の3つに集約されます。①接続数・エージェント数の上限に達した、②メモリが枯渇してエージェントを作れない、③サーバ側が停止・強制切断した。この記事では、この3系統をどう切り分け、どのコマンドで犯人を特定するかを解説します。
- ピーク時間帯だけ
SQL1224Nが出る、という間欠障害を追っている人 - 接続数の上限設計(
MAX_CONNECTIONS等)の勘所を掴みたい人 - 「接続が勝手に切れる」現象の原因を、サーバ側から確認したい人
対象は Db2 LUW(Linux/UNIX/Windows)です。コマンドは Db2 11.x / 12.x で確認しています。
まず結論:エージェントは「上限」か「メモリ」か「停止」で作れなくなる
Db2はクライアント接続を コーディネーター・エージェントという単位で処理します。このエージェントが作れない/維持できないと SQL1224N になります。作れなくなる理由は次のとおりです。
| 系統 | 典型的な原因 | 効いてくる設定 |
|---|---|---|
| ①上限到達 | 同時接続/エージェント数が上限に達した | MAX_CONNECTIONS / MAX_COORDAGENTS / MAXAPPLS |
| ②メモリ枯渇 | エージェント用メモリが確保できない | INSTANCE_MEMORY / OSの ulimit |
| ③サーバ停止 | db2stop / QUIESCE / FORCE で切られた | (運用操作・障害) |
間欠的に「ピーク時だけ出る」なら①か②、「ある時刻から一斉に出た」なら③を先に疑います。ただし上限に達した瞬間に SQL1224N になるとは限りません。実機で MAXAPPLS を超えて接続すると SQL1040N(57030)が返り、SQL1224N にはなりませんでした。db2 "? SQL1224N" の Explanation には “insufficient coordinator agents” が明記されているので、上限が原因になる経路は製品として存在します。実際に SQL1224N をそのまま返したのは③でした。
系統①:接続数・エージェント数の上限に達していないか
まず現在の上限設定を確認します。Db2の接続まわりは複数のパラメーターが連動するので、まとめて見ます。
# 接続・エージェント関連の上限をまとめて確認
db2 "GET DBM CFG" | grep -iE "MAX_CONNECTIONS|MAX_COORDAGENTS|MAXAGENTS|NUM_POOLAGENTS"
# データベース単位の最大接続数
db2 "GET DB CFG FOR <DB名>" | grep -i MAXAPPLS
| パラメーター | 意味 |
|---|---|
MAX_CONNECTIONS |
インスタンスが受け付ける最大の論理接続数 |
MAX_COORDAGENTS |
同時に動けるコーディネーター・エージェントの最大数 |
MAXAPPLS |
データベースごとの最大同時接続数(AUTOMATIC推奨) |
次に、今どれだけ接続を使っているかを見て、上限に張り付いていないかを確認します。ここは MON_GET 表関数が使えます。
# エージェント数・接続数の現在値と最大到達値
db2 "SELECT DB2_STATUS, TOTAL_CONNECTIONS, NUM_COORD_AGENTS, COORD_AGENTS_TOP
FROM TABLE(MON_GET_INSTANCE(-1)) AS T"
# 現在の接続数(アプリケーション単位)
db2 "SELECT COUNT(*) AS CONNECTIONS
FROM TABLE(MON_GET_CONNECTION(NULL, -2)) AS T"
# エージェントの使用状況(プール・実行中の内訳)
db2pd -agents | head -20
見るのは COORD_AGENTS_TOP(コーディネーター・エージェントの最大到達数)と MAX_COORDAGENTS の差です。ピーク時でも上限に届いていなければ、エージェント不足の線は消せます。AGENTS_TOP という列は MON_GET_INSTANCE に存在しないので、COORD_AGENTS_TOP か AGENTS_REGISTERED_TOP を使います。
「上限に張り付いている」とき、上限を上げる前に接続がきちんとクローズされているかを疑ってください。アプリがコネクションプールから借りた接続を返さない(リークする)と、じわじわ接続が積み上がり、あるとき上限に達します。上限を上げても、リークがあれば時間が延びるだけで再発します。接続開始が古いまま居座り続けている接続がないか、下のクエリで確認しましょう(CONNECTION_START_TIME が古い=長く生き残っている接続)。
db2 "SELECT APPLICATION_HANDLE, APPLICATION_NAME,
CLIENT_IPADDR, CONNECTION_START_TIME
FROM TABLE(MON_GET_CONNECTION(NULL, -2)) AS T
ORDER BY CONNECTION_START_TIME ASC
FETCH FIRST 20 ROWS ONLY"
系統②:メモリが足りずエージェントを作れないケース
接続数に余裕があるのに SQL1224N が出るなら、エージェント用のメモリが確保できていない可能性があります。INSTANCE_MEMORY の上限に達している、あるいはOS側の ulimit(プロセス数・メモリ)で頭打ちになっているパターンです。
# インスタンスメモリの上限と使用量を確認
db2 "SELECT MEMORY_SET_TYPE,
MEMORY_SET_USED / 1024 / 1024 AS USED_MB,
MEMORY_SET_SIZE / 1024 / 1024 AS SIZE_MB
FROM TABLE(MON_GET_MEMORY_SET('DBMS', NULL, -2)) AS T"
# db2diag.log にメモリ/エージェント生成失敗が出ていないか
db2diag -gi "message:=agent" -H 1d
このとき db2diag.log には、メモリ確保失敗やエージェント生成失敗を示すメッセージ(ADM系や Resource temporarily unavailable など)が出ているはずです。OSの ulimit -a(特に max user processes と max memory)も、Db2インスタンスユーザーで確認します。
db2diag -g は検索値の大文字小文字を区別します。-g "message:=Agent" は agent にマッチしないので、大小を無視する -gi に統一するのが安全です。
系統③:サーバ側の停止・強制切断で切られたケース
「ある時刻を境に、全接続が一斉に SQL1224N になった」なら、サーバ側の操作・障害を疑います。次のような操作は、進行中のリクエストを打ち切ります。
FORCE APPLICATION:特定接続の強制切断。切られたセッションが次に投げた1文がSQL1224N、2文目以降はSQL1024N(08003)になります。TCP/IP 接続ならSQL30081N(recv)です。QUIESCE(静止化):FORCE CONNECTIONSを付けると既存接続を切るので、切られたローカル接続が次の要求を投げるとSQL1224Nになります。静止化中の新規接続はこれとは別で、SQL20157N(08004)です。メッセージ末尾に"QUIESCE DATABASE"/"QUIESCE RESTRICTED ACCESS"とモードが入ります。インスタンス所有者(SYSADM)は静止化中でも接続できるため、「DBAは繋がるのにアプリだけ繋がらない」形で表面化します。UNQUIESCEのかけ忘れが地味に多い落とし穴です。db2stop(特にdb2stop force):インスタンス停止。停止後の新規接続は、ローカルがSQL1032N(57019)、TCP/IP がSQL30081N(connect/ errno 111)で、SQL1224Nにはなりません。- 異常終了(トラップ):db2sysc の異常終了。
db2diag.logやdb2dump配下のトラップファイルを確認します。
# 静止化(QUIESCE)されていないか。ヘッダーが -- Quiesced -- になる
db2pd -agents | head -3
# db2diag.log から QUIESCE の記録を拾う
db2diag -gi "message:=ADM75" -H 1d
QUIESCE は ADM7506W/ADM7507W(データベース単位、解除は ADM7509W)、ADM7500W/ADM7501W(インスタンス単位、解除は ADM7504W/ADM7503W)として記録されます。一方、FORCE APPLICATION による SQL1224N は既定の DIAGLEVEL 3 では db2diag.log に残りませんでした。ADM75 が見つからないことは「何も起きていない」の根拠になりません。その時刻に走ったバッチ・運用手順・監視ツール・HADR の TAKEOVER から当たります。
SQL1224N はサーバ側の状態が原因であることがほとんどなので、発生時刻を持ってサーバの db2diag.log を突き合わせるのが基本の一手です。ただし FORCE APPLICATION のように痕跡が残らない操作があり、ログだけでは切り分けられないケースがあります。接続数・メモリ・DB状態を時系列で残す監視があると、この穴を埋められます。
SQL1224N が出たときのチェックリスト
- まず新規接続が失敗したのか、接続済みのセッションが途中で切られたのかを確認する。
SQL1224Nは後者。直後にSQL1024Nが続いていれば同じ接続の続き - 接続経路を確認する。
db2 list applicationsのApplication Idが*LOCAL.で始まるものがローカル(IPC)接続。TCP/IP のクライアントならSQL30081N/SQL30108N側を探す db2pd -agentsのヘッダーを見る。-- Quiesced --なら静止化中、Unable to attachならインスタンスが停止しているMAX_CONNECTIONS/MAX_COORDAGENTS/MAXAPPLSの上限と、MON_GET_INSTANCEのCOORD_AGENTS_TOPを突き合わせる。ピークが上限に届いていなければエージェント不足の線は消える- 上限に張り付いているなら、上げる前に接続リーク(返し忘れ・長時間アイドル)を疑う
- 接続に余裕があるなら
INSTANCE_MEMORYと OSのulimit、db2diag.logのメモリ/エージェント失敗を確認 - 一斉発生なら サーバ側
db2diag.logのADM75を確認。無ければFORCE APPLICATIONを疑う(FORCEは残らない) - アプリ側は
SQL1224Nを再接続でリトライできるエラーとして扱う。実測では切断後のCONNECTは即座に通った
それでも切り分からないとき(実機ログつきの詳解)
FORCE・QUIESCE・db2stop force・各種の接続数上限を一つずつ再現した実測一覧、接続経路ごとに返るコードの対応表、db2diag.log に残るもの・残らないものの確認手順まで含めた詳しい解説は、Zennのフル記事にまとめています。
関連: SQL1032N インスタンス未起動 / MON_GET の値がリセットされる原因 / SQL0964C トランザクションログがいっぱい
Db2の運用で踏んだ地雷や、この記事で扱ってほしいテーマがあれば、ぜひコメントで教えてください。次の記事のネタにさせてもらいます。
この記事で触れたロック競合の切り分けは、Db2運用のごく一部です。ロックエスカレーションの仕組み・LOCKLIST/MAXLOCKSの設計・STMMとの付き合い方まで踏み込んだ内容を、本書 第8章「メモリ管理とロック競合の解消」にまとめています。
現場で引ける Db2 の教科書
現場で引ける!Db2実践エンジニア・バイブル
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ―― そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にまとめました。書いてあることはすべて実際の現場で経験したことです。
アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集 ―― 全12章+運用シェルスクリプト集。