2.6.1 PL/SQLの既知の不具合

Oracle Database18cでのPL/SQLの不具合を次に示します。

2.6.1.1 Oracle Bug#5910872

18cより前のOracle Databaseリリースでは、データをALLDBAUSER_ARGUMENTSのユーザー・ビューを使用して表示できるように、PL/SQLコンパイラはPL/SQLパッケージ・タイプ引数およびそのすべてのネストされた型のメタデータを収集し、そのデータをディクショナリ表に挿入していました。たとえば、パッケージNestedTypesExampleでの次のタイプ宣言を考えてみます。

Type Level2Record is RECORD (Field1 NUMBER); Type Level1Collection is TABLE of 
Level2Record index by binary_integer; Type Level0Record is RECORD (Field1 
Level1Collection); Procedure NestedTypesProc (Param1 Level0Record);

ALLDBAUSER_ARGUMENTSユーザー・ビューが問い合せられると、NestedTypeProcプロシージャの最上位タイプである、パラメータParam1Level0Recordが、Level0Record内のすべてのネストされた型の拡張説明とともに返されます。

SQL> select argument_name,type_subname,position,sequence,data_level from 
user_arguments where object_name='NESTEDTYPESPROC'; 
ARGUMENT_NAME    TYPE_SUBNAME       POSITION    SEQUENCE  DATA_LEVEL 
---------------  -----------------  ----------  --------  ---------- 
PARAM1           LEVEL0RECORD              1           1           0 
FIELD1           LEVEL1COLLECTION          1           2           1 
                 LEVEL2RECORD              1           3           2 
FIELD1                                     1           4           3

PL/SQLパッケージ・タイプの説明的なメタデータには、最上位のオブジェクト・タイプのメタデータにアクセスする場合と同じ方法ではアクセスできなかったため、このメタデータが格納されます。トップ・レベルのオブジェクト型およびコレクションでは、ALL_TYPESおよび関連するユーザー・ビューALL_TYPE_ATTRSおよびALL_COLL_TYPESを問い合せてタイプ・メタデータを取得できます。しかし、Oracle Database 12cリリース1 (12.1)より前は、PL/SQLパッケージ・タイプ(レコードやパッケージ化されたコレクションなど)のタイプ・メタデータを取得することはできませんでした。そのため、これらのPL/SQLパッケージ・タイプを参照する関数やプロシージャのパラメータにより、これらのタイプに関するすべてのメタデータをARGUMENTSビューに、ネストされたタイプを含めて公開していました。

深くネストされたタイプはSYS表領域で大量のメモリーを消費する可能性があります。また、ARGUMENTSビューでタイプ・メタデータを共有する方法がないため、深くネストされたタイプがある各パラメータにおいて独自にタイプ・メタデータの冗長コピーが必要になります。ARGUMENTSビューおよびSYS表領域のメタデータの量が膨大になると、PL/SQLコンパイラのパフォーマンスの低下を含む様々な問題へとつながりかねません。パフォーマンス低下の原因は、PL/SQLが基礎となるディクショナリ表の行を更新するのに多くの時間を要することです。

回避策:

Oracle Database 12cリリース1 (12.1)では、PL/SQLのパッケージ・タイプのサポートが強化され、これには新しいユーザー・ビューのALL_PLSQL_TYPESALL_PLSQL_TYPE_ATTRSALL_PLSQL_COLL_TYPESが含まれます。名前が示すように、これらのビューを使用してユーザーはPL/SQLパッケージ・タイプに関するメタデータを問い合せることができます。

Oracle Database 12cリリース1 (12.1)でこのパッケージ・タイプのサポートが追加されたことにより、PL/SQLコンパイラにおいて大量の説明的メタデータをARGUMENTSビューに挿入する必要はなくなりました。各パラメータ・タイプのARGUMENTSビューにおいて必要なのはタイプ名を含む単一のメタデータ行のみでした。PL/SQLタイプのビューに対する問合せにおいて、タイプ名およびネストされたタイプの完全な詳細を取得できます。

Oracle Databaseリリース18cからはARGUMENTSビューに含まれる行の数が減ります。具体的には、最上位レベル(DATA_LEVEL=0)アイテムのみがARGUMENTSビューに格納されます。

たとえば、前述の問合せをOracle Databaseリリース18cで実行すると、返される行の数が次のように減少します(DATA_LEVEL=0である行のみ)。

ARGUMENT_NAME    TYPE_SUBNAME       POSITION    SEQUENCE  DATA_LEVEL 
---------------  -----------------  ----------  --------  ---------- 
PARAM1           LEVEL0RECORD              1           1           0

OCIDescribeAny()は、ARGUMENTSビューで使用されるのと同じメタデータに基づいています。OCIDescribeAny()も、12cリリース1 (12.1)での変更前にそうであったように複数の行を返すのではなく、各パラメータ・タイプに対して単一行を返します。

ALLDBAおよびUSER_ARGUMENTSユーザー・ビューにも新しい列タイプTYPE_OBJECT_TYPEが含まれます。TYPE_OWNERTYPE_NAMEおよびTYPE_SUBNAMEによって記述されるタイプのタイプを判別するには、TYPE_OBJECT_TYPE列を使用します。使用可能な値には、TABLEVIEWPACKAGEおよびTYPEがあります。

引数のメタデータを収集するために以前の動作を必要とする場合は、イベントをevents='10946, level 65536'に設定します。このイベントを設定するとARGUMENTSビューはOracle Database 18cより前のOracle Databaseリリースでの動作に戻り、DATA_LEVEL0より大きくでき、タイプおよびネストされたタイプの説明的メタデータがビューに含まれるようになります。この変更を行う場合は、イベントを設定した後に、影響を受けるパッケージを再コンパイルする必要があります。影響を受けるパッケージの再コンパイル時に、コンパイラにより追加のメタデータが再収集されます。このイベントはまた、OCIDescribeAny()をOracle Database 18cより前のリリースの動作に戻します。

Oracle Database 12cリリース1 (12.1.0.2)以降では、引数なしでプロシージャを入力するとARGUMENTSビューには行は表示されません。これは、ARGUMENTSビューの行を減らす変更とは別の追加の変更です。Oracle Database 12cリリース1 (12.1.0.2)より前は、引数なしのプロシージャはARGUMENTSビューに単一行として表示されていました。