■エラー内容
ORA-12516: TNS: リスナーは、一致するプロトコル・スタックが使用可能なハンドラを
検出できませんでした。
■原因
停電などでHUBの電源が落ちた際、クライアントPCとデータベースが一度にたくさん
切断される場合がある。このとき、データベース側には、これまで接続していた
プロセス・セッションが残っている。復旧後に、クライアントPCから接続されると
新たにプロセス・セッションがデータベースのメモリに割り当てされる。
つまり、サーバ上のメモリ使用量が倍近くに膨らんでしまい、もうメモリ不足(正確には
データベースのプロセス・セッション用に割り当て可能な上限値を超えてしまう)
で新たな接続は認めないというエラーが返ってきている。
いわゆるゾンビプロセスは、時間が経てば無くなっていくため、下記の対処を
行わなくても、待てば解決する場合もある。(端末の台数によるが1時間半程度)
■方針
接続が残っているセッションを強制終了する
■手順
①SYSでログインする
sqlplus sys/パスワード@detabase名 as sysdba
②表示幅の調節
set linesize 1000
③セッションを確認する
最大値に達していれば、エラー原因と考えてよい
(新たな接続が制限され、なかなかつながらない状況)
SELECT
RESOURCE_NAME リソース名,
CURRENT_UTILIZATION 現在数,
MAX_UTILIZATION 最大数,
LIMIT_VALUE 上限
FROM
V$RESOURCE_LIMIT
WHERE
RESOURCE_NAME IN ('processes','sessions');
リソース名 現在数 最大数 上限
------------------------------------------
processes 198 200 200
sessions 197 200 200
④具体的なセッションを一覧表示する
machine
が端末名、
LOGON_TIME
がログイン時間、
sid
と
serial#
がセッションを強制終了する際に必要となる項目
SELECT
S.machine,
TO_CHAR(S.LOGON_TIME, 'YYYY/MM/DD HH24:MI:SS') LOGON_TIME,
S.sid,
S.serial#,
P.PID ORACLE_PID,
P.SPID OS_PID,
S.STATUS,
S.USERNAME ORACLE_USER,
S.OSUSER OS_USER,
S.TERMINAL,
S.PROGRAM
FROM
V$PROCESS P
LEFT OUTER JOIN V$SESSION S
ON P.ADDR = S.PADDR
WHERE
P.BACKGROUND IS NULL AND
P.PID > 1
ORDER BY
S.machine,
TO_CHAR(S.LOGON_TIME, 'YYYY/MM/DD HH24:MI:SS');
⑤重複しているセッションを強制終了する
同一マシーンで、古いログイン時間で、STATUSがACTIVEでなければ、
強制終了の対象として検討する。
間違えた場合は、危険を伴うためユーザーの責任で実行すること
文法:alter system kill session 'sid,serial#';
例:alter system kill session '100,123'
実行後、commitする
■対策
物理メモリに余裕があれば、プロセス数、セッション数の上限を増やす。
ただし、PGAのメモリ割り当てが少ないと別のエラー原因になるため、
単純に増やせばいいわけではない。また、ORACLEインスタンスの再起動が
必要になるため、実行する際は注意が必要である。まずは自分のローカル環境で
試しに増やして実験してみるとよいだろう。
SYSユーザーにて以下を実行
alter system set processes = xxx scope=spfile;
alter system set sessions = xxx scope=spfile;
データベースにいきなり接続できなくなると影響がかなり大きいため
日頃から、プロセス数、セッション数、SGA、PGAのメモリ状況などは
チェックするようにしておきたい。