SERIALLY_REUSABLEパッケージ

SERIALLY_REUSABLEパッケージを使用すると、スケーラビリティを向上させるためにメモリーをより効率的に管理するアプリケーションを設計できます。

パッケージがSERIALLY_REUSABLEでない場合、そのパッケージ状態は各ユーザーのユーザー・グローバル領域(UGA)に格納されます。したがって、UGAのメモリー量をユーザー数に比例して増加させる必要があり、スケーラビリティが制限されます。パッケージの状態はセッションが存続する間維持でき、UGAメモリーはセッションが終了するまでロックされます。Oracle Officeなどの一部のアプリケーションの標準的なセッションは数日間存続します。

パッケージがSERIALLY_REUSABLEである場合、そのパッケージ状態はシステム・グローバル領域(SGA)内の小規模なプールにある作業領域に格納されます。パッケージの状態は、サーバー・コールが存続する間のみ維持されます。サーバー・コールの後、作業領域はプールに戻されます。以降のサーバー・コールがこのパッケージを参照すると、Oracle Databaseはこのプールからインスタンス化を再利用します。インスタンス化を再利用すると、インスタンス化は再初期化されるため、それまでのサーバー・コールで実行されたパッケージ状態に対する変更は参照できなくなります。(初期化の詳細は、「パッケージのインスタンス化および初期化」を参照してください。)

ノート:

データベース・トリガー、またはSQL文から起動される他のPL/SQLサブプログラムからSERIALLY_REUSABLEパッケージにアクセスしようとするとエラーが発生します。

ここでのトピック

SERIALLY_REUSABLEパッケージの作成

SERIALLY_REUSABLEパッケージを作成するには、SERIALLY_REUSABLEプラグマをパッケージ仕様部とパッケージ本体(存在する場合)に含めます。

例11-4では、きわめて単純なSERIALLY_REUSABLEパッケージを2つ作成します。1つは仕様部のみで、もう1つは仕様部と本体があります。

例11-4 SERIALLY_REUSABLEパッケージの作成

-- Create bodiless SERIALLY_REUSABLE package:
 
CREATE OR REPLACE PACKAGE bodiless_pkg AUTHID DEFINER IS
  PRAGMA SERIALLY_REUSABLE;
  n NUMBER := 5;
END;
/
 
-- Create SERIALLY_REUSABLE package with specification and body:
 
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER IS
  PRAGMA SERIALLY_REUSABLE;
  n NUMBER := 5;
END;
/
 
CREATE OR REPLACE PACKAGE BODY pkg IS
  PRAGMA SERIALLY_REUSABLE;
BEGIN
  n := 5;
END;
/

SERIALLY_REUSABLEパッケージの作業単位

SERIALLY_REUSABLEパッケージの作業単位はサーバー・コールです。

このパッケージのパブリック変数は、作業単位内のみで使用する必要があります。

ノート:

誤って以前の作業単位で設定されたパブリック変数の値に依存した場合、そのプログラムは失敗する可能性があります。PL/SQLではこのようなケースはチェックできません。

SERIALLY_REUSABLEパッケージの作業単位(サーバー・コール)が完了した後、Oracle Databaseにより次の処理が実行されます。

  • オープンされているすべてのカーソルのクローズ処理。

  • 再使用不可のメモリーの一部を解放する処理(たとえば、コレクション変数用のメモリー、長いVARCHAR2用のメモリーなど)。

  • このパッケージのインスタンス化を、このパッケージ用に保持された再使用可能インスタンス化のプールに戻す処理。

例11-5 SERIALLY_REUSABLEプラグマの影響

この例では、本体のないパッケージpkgsr_pkgは、sr_pkgSERIALLY_REUSABLEpkgはそうでないという点以外同じです。各パッケージで、初期値に5が指定されたパブリック変数nを宣言します。その後、無名ブロックで各変数の値を10に変更します。次に、別の無名ブロックで各変数の値を出力します。pkgの状態はセッションが存続する間維持されるため、pkg.nの値は10のままです。sr_pkgの状態はサーバー・コールが存続する間のみ維持されるため、sr_pkg.nの値は5です。

CREATE OR REPLACE PACKAGE pkg IS
  n NUMBER := 5;
END pkg;
/

CREATE OR REPLACE PACKAGE sr_pkg IS
  PRAGMA SERIALLY_REUSABLE;
  n NUMBER := 5;
END sr_pkg;
/

BEGIN
  pkg.n := 10;
  sr_pkg.n := 10;
END;
/

BEGIN
  DBMS_OUTPUT.PUT_LINE('pkg.n: ' || pkg.n);
  DBMS_OUTPUT.PUT_LINE('sr_pkg.n: ' || sr_pkg.n);
END;
/

結果:

pkg.n: 10
sr_pkg.n: 5

SERIALLY_REUSABLEパッケージの明示カーソル

SERIALLY_REUSABLEパッケージの明示カーソルは、パッケージをクローズするかパッケージの作業単位(サーバー・コール)が終了するまでオープンされたままになります。カーソルを再度オープンするには、新しいサーバー・コールを作成する必要があります。例11-6に示すとおり、サーバー・コールがサブプログラム起動と異なる場合があります。

対照的に、SERIALLY_REUSABLEでないパッケージの明示カーソルは、パッケージをクローズするかセッションから切断するまでオープンされたままになります。

例11-6 コール境界でオープンされるSERIALLY_REUSABLEパッケージのカーソル

DROP TABLE people;
CREATE TABLE people (name VARCHAR2(20));
 
INSERT INTO people (name) VALUES ('John Smith');
INSERT INTO people (name) VALUES ('Mary Jones');
INSERT INTO people (name) VALUES ('Joe Brown');
INSERT INTO people (name) VALUES ('Jane White');

CREATE OR REPLACE PACKAGE sr_pkg IS
  PRAGMA SERIALLY_REUSABLE;
  CURSOR c IS SELECT name FROM people;
END sr_pkg;
/
 
CREATE OR REPLACE PROCEDURE fetch_from_cursor IS
  v_name  people.name%TYPE;
BEGIN
  IF sr_pkg.c%ISOPEN THEN
    DBMS_OUTPUT.PUT_LINE('Cursor is open.');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Cursor is closed; opening now.');
    OPEN sr_pkg.c;
  END IF;
 
  FETCH sr_pkg.c INTO v_name;
  DBMS_OUTPUT.PUT_LINE('Fetched: ' || v_name);
 
  FETCH sr_pkg.c INTO v_name;
    DBMS_OUTPUT.PUT_LINE('Fetched: ' || v_name);
  END fetch_from_cursor;
/
 

サーバーへの1回目のコール:

BEGIN
  fetch_from_cursor;
  fetch_from_cursor;
END;
/

結果:

Cursor is closed; opening now.
Fetched: John Smith
Fetched: Mary Jones
Cursor is open.
Fetched: Joe Brown
Fetched: Jane White
 

サーバーへの新たなコール:

BEGIN
  fetch_from_cursor;
  fetch_from_cursor;
END;
/

結果:

Cursor is closed; opening now.
Fetched: John Smith
Fetched: Mary Jones
Cursor is open.
Fetched: Joe Brown
Fetched: Jane White