2012年3月31日土曜日

ORA-12516 エラーの原因・対処

■エラー内容
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のメモリ状況などは
チェックするようにしておきたい。


0 件のコメント:

コメントを投稿