DBAtlas · データベース運用アトラス

コネクションストーム (接続数過多)

症状

'too many connections'、'ORA-00018'、'remaining connection slots reserved' — 新規接続が拒否されている。

1. 現在の状態を測定する

接続数はいくつで、上限はいくつか。アクティブとアイドルはそれぞれいくつか。

Oracle

SELECT COUNT(*) total, SUM(CASE WHEN status='ACTIVE' THEN 1 ELSE 0 END) active FROM v$session WHERE type='USER';

PostgreSQL

SELECT count(*), state FROM pg_stat_activity WHERE backend_type = 'client backend' GROUP BY state;

MySQL

SHOW STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';

SQL Server

SELECT COUNT(*), status FROM sys.dm_exec_sessions WHERE is_user_process=1 GROUP BY status;

Redis

INFO clients

2. 発生元を特定する: 誰が、どこから

どのアプリケーション/ホスト/ユーザーが接続を開いているか。通常は単一のアプリケーションサーバーのプールが膨張しているか、接続リーク (大量の idle in transaction セッション) がある。

PostgreSQL

SELECT client_addr, usename, state, count(*) FROM pg_stat_activity WHERE backend_type = 'client backend' GROUP BY 1,2,3 ORDER BY 4 DESC;

MySQL

SELECT host, user, count(*) FROM information_schema.processlist GROUP BY host, user ORDER BY 3 DESC;

SQL Server

SELECT host_name, program_name, login_name, COUNT(*) FROM sys.dm_exec_sessions WHERE is_user_process=1 GROUP BY host_name, program_name, login_name ORDER BY 4 DESC;

3. すぐに余裕を確保する

長時間アイドル/idle in transaction の接続をクリーンアップする。必要なら、問題のアプリケーションの接続を一括で切断する。管理者ログイン用に予約されたスロット (PG superuser_reserved_connections) を使う。

4. 正しい対策: コネクションプーリング

max_connections を無制限に上げるとメモリを消費し、問題を先送りするだけである。正しい対策は、アプリケーション側のコネクションプール (HikariCP、PgBouncer、ProxySQL) を妥当なプールサイズで使うこと。プールサイズは通常 (コア数*2 + ディスク数) 程度 — ツール > Connection Pool 計算ツールを参照。

5. リークと再発を防止する

アプリケーションが接続を確実にクローズするようにする (finally/using)。idle_in_transaction_session_timeout と wait_timeout を設定する。接続数のアラートを設定する。

DBAtlas で開く →