ORA-20,ORA-00020の原因と対処
対応バージョン
Oracle Database 11.2 - 12.1
2015-02-10出力メッセージについて記載、言い回しなどの文言修正(内容修正なし)
2014-12-01記事公開
ORA-20はORA-1555等のように、運用を続けているうえでよく散見されるエラーとなりますので、DBA運用経験の間もない方でもエラーに遭遇することが多いかと思います。
メッセージ
ORA-00020: 最大プロセス数(string)を超えました。
ORA-00020: maximum number of processes (string) exceeded.
発生原因
ORA-20はOracle Databaseで設定したプロセス数の設定値を超えてプロセスが起動した場合に発生するエラーです。このプロセスにはOracle Databaseのシステムで使用されるバックグラウンド・プロセスを含みます。
発生要因例
よくあるのはシステムの肥大化やユーザ数の増加、プログラムのバグにより発生する事があります。
プログラムのバグの例でいうと、JDBCから直接接続を行い、不要なコネクションをクローズせずに次のコネクションを開始するなど、正しい使い方をしていない場合や、Oracle Databaseのソフトウェアバグ等です。
他には設定値の変更によって、アーカイブプロセスや、パラレルスレーブの数を増やした際に、そちらを起因として発生することがあります。
対処方法
基本的にはPROCESSES初期化パラメータを増やすことにより対処を行います。
※ PROCESSESの変更にはインスタンスの再起動を伴います。
同時にSESSIONSについても増加する必要がありますが、設定なしであれば自動で適正値に変更されます。
但し、共有サーバ・モードでの接続を行っており、PROCESSESより算出されるデフォルト値(1.5 * PROCESSES + 22)より大きな値をとっている場合がありますので、その場合はSESSIONSの値は小さくしないでください。
共有サーバ・モード環境ではSESSIONSの値を バックグラウンドプロセスを含めた想定ユーザ最大接続数 * 1.1 の合計 程度にすることを推奨しています。
参考資料
https://docs.oracle.com/cd/E16338_01/server.112/b56311/initparams234.htm
Oracle Databaseリファレンス 11gリリース2 (11.2)
B56311-12
SESSIONS
PROCESSESの増加に伴い、OS側でのリソース増加も必要な場合があります。
例えばLinuxではulimit -aにて出力される、プロセス数の最大値やカーネルパラメータのセマフォの変更です。
また、プロセス数の異常が認められる場合は、発生起因となった処理の特定をする必要があります。(日毎にプロセス数が増加していくプログラムがないかなどを探ります)
対処例
以下PROCESSESの増加の対処例を記載します。
SPFILEを使用している場合の変更
SQL*Plusにログイン後、以下のコマンドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ sqlplus / as sysdba -- 以下コマンドにて使用しているspfileのパスが出力される場合は、SPFILEを使用しています。 SQL> show parameter spfile SQL> set line 120 pages 1000 trim on SQL> col name for a15 SQL> col value for a20 SQL> col sid for a10 -- 現在値の確認 SQL> select INST_ID, NAME, VALUE from gv$parameter where name in ('processes','sessions'); -- SPFILEの内容の確認 SQL> select SID, NAME, VALUE from gv$spparameter where name in ('processes','sessions'); -- バックアップ取得 SQL> create pfile='<フルパス指定のバックアップファイル名>' from spfile; |
SQL> startup pfile='<フルパス指定のバックアップファイル名>'
SQL> create spfile from pfile='<フルパス指定のバックアップファイル名>'; -- DBが停止している状態でも作成可能です。
1 2 3 |
-- 値の変更 SQL> ALTER SYSTEM SET PROCESSES = <変更後の値> SCOPE=SPFILE; SQL> ALTER SYSTEM RESET SESSIONS; |
ORA-32010: SPFILEには削除するエントリが見つかりません
また共有サーバ・モードによる接続の場合はセッション数を大きくとっている場合があります。その場合はSESSIONSの値をリセットしないように気を付けてください。
1 2 |
-- SPFILEの内容が更新されていることの確認 SQL> select SID, NAME, VALUE from gv$spparameter where name in ('processes','sessions'); |
対象インスタンスの再起動後、反映されているかを確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
-- インスタンスを再起動します。 SQL> shutdown immediate SQL> startup SQL> set line 120 pages 1000 trim on SQL> col name for a15 SQL> col value for a20 SQL> col sid for a10 -- 現在値の確認 SQL> select INST_ID, NAME, VALUE from gv$parameter 2 where name in ('processes','sessions'); -- SPFILEの内容の確認 SQL> select SID, NAME, VALUE from gv$spparameter 2 where name in ('processes','sessions'); SQL> exit |
PFILEを使用している場合の変更
SQL*Plusにログイン後、以下のコマンドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ sqlplus / as sysdba -- SPFILEのVALUEに値がなく、PFILEで起動されていることを確認します。 SQL> show parameter spfile SQL> set line 120 pages 1000 trim on SQL> col name for a15 SQL> col value for a20 SQL> col sid for a10 -- 現在値の確認 SQL> select INST_ID, NAME, VALUE from gv$parameter 2 where name in ('processes','sessions'); SQL> exit |
以下のファイルのPROCESSESの値を変更します。(例として400にする場合の行を記載)
対象ファイル: [ORACLE_HOME]/dbs/init<インスタンス名>.ora
1 |
*.processes = 400 |
PROCESSESの行がない場合は、行を追加してください。
アルファベット大文字と小文字の区別はありません。
インスタンスの再起動後、値が反映されているか確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ sqlplus / as sysdba -- インスタンスを再起動します。 SQL> shutdown immediate SQL> startup -- SPFILEのVALUEに値がなく、PFILEで起動されていることを確認します。 SQL> show parameter spfile SQL> set line 120 pages 1000 trim on SQL> col name for a15 SQL> col value for a20 SQL> col sid for a10 -- 現在値の確認 SQL> select INST_ID, NAME, VALUE from gv$parameter SQL> where name in ('processes','sessions'); SQL> exit |
エラー原因の確認と値の検討
データベースで発生した場合
プロセス数不足によるバックグラウンド・プロセス等の異常終了では、アラートログに以下のようなメッセージが出力されます。
※ORA-20により、バックグラウンドプロセスが異常終了することで他のエラーが併発することがよくあります。
SQL*Plus等のクライアントなどで新規接続をする場合には直接ORA-20が戻されます。
PROCESSESはユーザが接続するプロセス数の他にバックグラウンド・プロセスも含んでいる事に注意してください。
バックグラウンド・プロセスはシステムによって数が異なりますが、性能問題によるバックグラウンド・プロセス数の増加措置や内部ジョブの設定などがない場合は、PROCESSESパラメータを50~100程度多く見込んで設定しておけば問題ありません。
PROCESSESを多く使用しているプログラムを確認する
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ sqlplus / as sysdba SQL> set line 120 pages 1000 trim on SQL> col username for a15 SQL> col machine for a30 SQL> col program for a30 SQL> col logon_time for a20 SQL> select s.username "USERNAME", s.machine "MACHINE", s.program "PROGRAM", 2 to_char(s.logon_time, 'yyyy/mm/dd') "LOGON_DATE", count(1) "COUNT" 3 from v$session s, v$process p 4 where s.paddr = p.addr 5 group by s.username, s.machine, s.program, to_char(s.logon_time, 'yyyy/mm/dd') 6 order by s.username, s.machine, s.program, to_char(s.logon_time, 'yyyy/mm/dd'); |
実行されているSQLを確認する
上記で出力したMACHINEやPROGRAMなどで対象を絞って出力してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SQL> set line 120 pages 1000 trim on SQL> col username for a15 SQL> col machine for a30 SQL> col program for a30 SQL> col logon_time for a20 SQL> select s.sid "SID", s.username "USERNAME", s.machine "MACHINE", s.program "PROGRAM", 2 to_char(s.logon_time, 'yy/mm/dd hh24:mi:ss') "LOGON_TIME", a.sql_text "SQL TEXT" 3 from v$session s, v$process p, v$sqlarea a 4 where s.paddr = p.addr 5 and s.sql_address=a.address(+) 6 and s.sql_hash_value=a.hash_value(+) 7 and s.audsid != USERENV('SESSIONID') 8 order by s.username, s.machine, s.program; |
上記の情報で値が決められない場合は、一旦値の増加を行いプロセスの状況を確認します。
ASMで発生した場合
ASM側のアラートログでは以下のようなエラーが確認できます。
※こちらのエラーが発生した場合、データベース側のアラートログではORA-20が発生します。
ASMでのプロセス数についての見積もりは基本的にできません。
但し、Oracleが推奨値を出しています。(マニュアルに記載されていますが、バージョンごとに推奨する見積もり値が違いますので注意してください。)
Oracle 11gR2であれば以下が推奨の値となります。
※ マニュアルの値も変わることがありますので最新の値はマニュアルを参照してください。
設定後にプロセス数に異常が発生しないかを監視する場合は、gv$resource_limitを確認する等して使用状況を確認することで監視を行います。
PROCESSESの使用状況を確認する
ASMへログインして確認してください
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ sqlplus / as sysasm SQL> set line 120 pages 1000 trim on SQL> col resource_name for a30 SQL> col limit_value for a12 SQL> select inst_id, resource_name,current_utilization, max_utilization, limit_value 2 from gv$resource_limit 3 where resource_name in ('processes', 'sessions') 4 order by inst_id, resource_name; -- CURRENT_UTILIZATION 現在使用されている(リソースまたはロック、プロセスの)数 -- MAX_UTILIZATION 最後にインスタンスを起動してからのこのリソースの最大消費量 -- LIMIT_VALUE リソースおよびロックの場合は無制限。(無制限の場合、UNLIMITED)。 |