25 OCI関数を使用したセッションレス・トランザクションの操作

セッションレス・トランザクションを使用すると、ユーザーは、一意のトランザクション識別子を指定してデータベース・セッションでトランザクションを開始し、作業単位を送信し、トランザクションを一時停止し、同じトランザクション識別子を使用して別のセッションで同じトランザクションを続行することができます。同じトランザクションを別のセッションからコミットまたはロールバックしてそのトランザクションを終了できます。

たとえば、トランザクションをインスタンス・セッション1で開始し、インスタンス・セッション2で続行し、最後にインスタンス3でセッション3からコミットできます。

この機能では、データベース・サーバーおよびクライアントで、次のアクティビティを実行するための関数が提供されます:
  • トランザクションに関して、ユーザーが指定した一意のトランザクション識別子を設定します
  • 指定したトランザクション識別子で新しいトランザクションを開始します
  • そのトランザクションを一時停止します
  • トランザクション識別子によって特定された既存のトランザクションを再開します
  • COMMITまたはROLLBACK関数を使用してそのトランザクションを終了します

ユーザーは、Oracle Call Interfaceの関数をコールしてOracle Databaseサーバーと対話できます。状態を維持するために、様々なタイプのサービス・コンテキスト・ハンドルが使用されます。

25.1 セッションレス・トランザクションで使用される概念

この項では、セッションレス・トランザクションで使用される概念について説明します。

25.1.1 グローバル・トランザクションID

すべてのセッションレス・トランザクションは、グローバル・トランザクションID(GTRID)と呼ばれる、ユーザーが指定した一意のトランザクション識別子によって特定される必要があります。これは、トランザクションのリカバリを含め、セッションレス・トランザクションのライフサイクルを最初から最後まで管理するために使用されます。

25.1.2 ラウンドトリップ

サーバー・ラウンドトリップは、クライアントからサーバーへ送信されたリクエストまたはデータ、およびクライアントへ送り返されたレスポンスとして定義づけられます。ラウンドトリップには、1つのメイン・コールが必要であり、ピギーバック関数が含まれている場合があります。

25.1.3 ピギーバック関数

サーバーへのラウンドトリップの回数を減らすため、OCIクライアント・ライブラリによってユーザーからのリクエストの受信時に必ずラウンドトリップが発生するわけではありません。かわりに、クライアント・ライブラリによって、それらのリクエストがピギーバック・リクエストとして格納され、それらが、ラウンドトリップのメイン・コールとしての役割を果たす必要がある次のリクエストにアタッチされます。Oracleサーバーでそのラウンドトリップが処理されるときは、通常は、最初にそれらのピギーバック関数リクエストが実行され(事前コール・ピギーバックと呼ばれる)、次にメイン・コールが実行されます。

ユーザーは、次のメイン・コールの後にそのトランザクションを一時停止するよう要求できます(事後コール・ピギーバックによる一時停止と呼ばれる)。サーバーによって、以降も、メイン・コールの前にこのようなピギーバック・リクエストが処理されますが、すぐに動作するのではなく、メイン・コールの前にこのリクエストが記録され、メイン・コールの後に発生するように一時停止操作が延期されます。

例25-1 事前コール・ピギーバック

int main()
{
  ...
  OCITransStart(svchp, errhp, 60, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);  /* a pre-call piggyback which starts a Sessionless transaction */
  OCIStmtExecute(...) /* a call that incurs a round-trip to server. This is the "main call". */
  ...
}

この例では、最初のOCIコール(OCITransStart)は事前コール・ピギーバックです。これは、OCIクライアント・ライブラリでこのリクエストが記録された直後に戻されます。ただし、まだこのリクエストはサーバーに送信されません。OCIStmtExecuteがコールされると、クライアント・ライブラリによってOCITransStart事前コール・ピギーバック・リクエストがOCIStmtExecuteメイン・コールとともに送信されます。サーバーでは、このパッケージが受信されると、OCITransStartが事前コール・ピギーバックであり、OCIStmtExecuteがメイン・コールであることが学習されます。そのため、OCStmtExecuteのプロシージャを呼び出す前に、OCITransStartに対応するプロシージャが呼び出されます。

事前コール・ピギーバックでエラーが戻された場合は、メイン・コールと、実行可能な、事後コール・ピギーバックによる一時停止は呼び出されません。

例25-2 事後コール・ピギーバックによる一時停止

int main()
{
   ...
  OCITransDetach(svchp, errhp, OCI_TRANS_SESSIONLESS | OCI_TRANS_POST_CALL));  
  /* a post-call piggyback which suspends a Sessionless transaction */
  OCIStmtExecute(...) /* a call that incurs a round-trip to server. This is the "main call". */
  ...
}

この例では、最初のOCIコール(OCITransDetach)は事後コール・ピギーバックです。これは、クライアント・ライブラリでこのリクエストが記録された直後に戻されます。ただし、まだこのリクエストはサーバーに送信されません。

OCIStmtExecute関数が呼び出されると、クライアント・ライブラリによって、OCITransDetach事後コール・ピギーバック・リクエストがOCIStmtExecuteメイン・コールとともに送信されます。サーバーでは、このパッケージが受信されると、OCITransDetachが事後コール・ピギーバックでありOCIStmtExecuteがメイン・コールであることが学習されます。そのため、最初に、メイン・コール(OCIStmtExecute)に対応するプロシージャが呼び出され、次に、OCITransDetachに対応するプロシージャが呼び出されます。

セッションがセッションレス・トランザクションに関連付けられているときに前述の例を実行した場合は、文が効果的に実行され(セッションレス・トランザクション内)、その後、当該セッションレス・トランザクションから一時停止されます。これらはすべて単一のラウンドトリップで行われます。メイン・コールでエラーが戻された場合は、実行可能な、事後コール・ピギーバックによる一時停止は呼び出されません。

25.1.4 セッションレス・トランザクション

セッションレス・トランザクションには、データベース内の任意のセッションから開始、一時停止、再開、コミットおよびロールバックする機能があります。たとえば、トランザクションをセッション1で開始し、セッション2で続行し、最終的にセッション3からコミットできます。なお、これらのセッションは、RAC構成内の様々なインスタンスからもたらされる可能性があります。

25.1.5 アクティブ・セッションレス・トランザクション

現在セッションに関連付けられているセッションレス・トランザクションが、アクティブであるとみなされます。新しいセッションレス・トランザクションを開始するか、既存のセッションレス・トランザクションを再開すると、このようなトランザクションが、アクティブ・セッションレス・トランザクションであるとみなされます。セッションレス・トランザクションが一時停止、コミットまたはロールバックされると、それはアクティブではなくなります。

25.2 OCIでのセッションレス・トランザクションのライフサイクル

セッションレス・トランザクションのライフサイクルには、同じデータベースに接続する任意のセッションから開始、一時停止、再開、コミットおよびロールバックする機能があります。

セッションレス・トランザクションは、サーバーまたはクライアントで開始できます。サーバー上でセッションレス・トランザクションを開始、再開および一時停止するための一連の関数は、クライアント上のそれらと相互運用可能ではありません。トランザクションを開始、一時停止または再開するための、クライアント側の関数では、そのトランザクションがサーバー上で非アクティブになるまで(つまり、一時停止、コミットまたはロールバックされるまで)、エラーが戻されます(逆の場合も同様)。

GTRIDが指定されていない場合、Oracle Call Interface (OCI)クライアントでは、開始トランザクション・リクエストとともにGTRIDが生成されます。Oracle Databaseサーバーに送信される後続の作業単位は、トランザクション・コンテキスト内にあります。時間の経過とともに、トランザクションが作業単位間で複数回、一時停止され再開される可能性があります。トランザクションは、そのトランザクションをコミットするかロールバックすると終了します。

関連項目:

25.2.1 OCIでセッションレス・トランザクションを使用するための前提条件

ユーザーは、トランザクション・ハンドルを割り当て、それをサービス・コンテキスト・ハンドルのOCI_ATTR_TRANSとして設定する必要があります。
OCISvcCtx *svchp = NULL;
 /* get a service context handle from the session pool. */
OCISessionGet (envhp, errhp, &svchp, authInfop, poolName, poolNameLen, NULL, 0,
               NULL, NULL, NULL, OCI_SESSGET_SPOOL | OCI_SESSGET_PURITY_NEW);
 
/* create a transaction handle */
OCITrans    *txnhp  = (OCITrans *)0;  /* Sessionless transaction */
OCIHandleAlloc(envhp, (void **)&txnhp, OCI_HTYPE_TRANS, 0, 0);
 
/* set txn handle as service context handle's OCI_ATTR_TRANS attribute */
OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, txnhp, 0, OCI_ATTR_TRANS, errhp);

25.2.2 OCIでのGTRIDの設定

GTRIDを指定する必要がある場合は、OCIAttrSetをコールして、そのGTRIDを含むXID構造体を、トランザクション・ハンドルのOCI_ATTR_XID属性として設定する必要があります。セッションレス・トランザクションでは、構造体XIDのデータ・メンバーformatIDおよびbqual_lengthは使用されません。

GTRIDを設定するためのサンプル・コード・スニペットを次に示します:

/* Get current transaction handle */
OCITrans *current_txnhp;
OCIAttrGet(svchp, OCI_HTYPE_SVCCTX, &current_txnhp, NULL,
           errhp);
 
/* set GTRID in XID struct */
XID         res_xid;
strcpy(res_xid.data, "client_user_gtrid_1");
res_xid.gtrid_length = strlen("client_user_gtrid_1");
 
/* set XID as txn handle's attribute */
OCIAttrSet(current_txnhp, OCI_HTYPE_TRANS, &res_xid, sizeof(XID), OCI_ATTR_XID, errhp);
XID属性をNULLに設定して、クライアント・ライブラリによって開始トランザクションでGTRIDを生成できるようにします。
OCIAttrSet(current_txnhp, OCI_HTYPE_TRANS, NULL, 0, OCI_ATTR_XID, errhp);

ノート:

次の条件ではXIDを設定できません:
  • PL/SQLファンクションを介して開始または再開されたアクティブなセッションレス・トランザクションがある場合、サービス・コンテキスト・ハンドルのOCI_ATTR_TRANS属性は、OCIライブラリによって管理される読取り専用トランザクション・ハンドルとなります。エラー26210を戻します。
  • OCIライブラリによって新しいアクティブなセッションレス・トランザクションが開始される場合は、そのGTRIDを設定前に取得する必要があります。エラー26204を戻します。「OCIでのGTRIDの取得」を参照してください。
  • アクティブなFlexトランザクションがOCIで開始され(新規または再開されたトランザクションとして)、そのGTRIDがOCIライブラリによって生成された場合。トランザクションがアクティブであるため、ユーザーはOCIでそのGTRIDを取得していません。エラー26204を戻します。
  • 新しいセッションレス・トランザクションを開始するか既存のセッションレス・トランザクションを再開するためのピギーバック・コールは、記録されていますが、データベース・サーバーにはまだ送信されていない。エラー26216を戻します。

    関連項目:

25.2.3 OCIでのGTRIDの取得

XIDからGTRIDを取得するには、OCIAttrGet関数をコールして、現在のトランザクション・ハンドルでのOCI_ATTR_XID属性(つまり、サービス・コンテキスト・ハンドルの属性OCI_ATTR_TRANS)を取得します。セッションレス・トランザクションを使用しているときは、取得したXID内のメンバー(GTRIDを含む)を変更しないでください。

アクティブなセッションレス・トランザクションがOCIクライアントで開始または再開された場合、取得されるXIDは、「OCIでのGTRIDの設定」の項の説明のとおり、最後に設定されたものである必要があります。トランザクションがサーバーで開始または再開された場合、トランザクション・ハンドルはOCIクライアント・ライブラリによって管理され、取得されるGTRIDはアクティブなセッションレス・トランザクションのGTRIDとなります。

アクティブなセッションレス・トランザクションがOCIクライアントで新たに開始され、OCIライブラリによってそのGTRIDが生成された場合、そのようなアクティブなセッションレス・トランザクションを一時停止する前に、アプリケーションで、生成されたGTRIDを取得する必要があります。つまり、アプリケーションで、OCIAttrGet関数をコールしてOCI_ATTR_XID属性を取得する必要があります。

OCITrans *current_txnhp;
XID      *current_xidp;
char      gtrid_buffer[65];
 
OCIAttrGet(svchp, OCI_HTYPE_SVCCTX, &current_txnhp, NULL, OCI_ATTR_TRANS, errhp);
OCIAttrGet(current_txnhp, OCI_HTYPE_TRANS, &current_xidp, NULL, OCI_ATTR_XID, errhp));
memcpy(gtrid_buffer, current_xidp->data, current_xidp->gtrid_length);

25.2.4 新しいセッションレス・トランザクションの開始

OCI_ATTR_TRANS属性とOCI_ATTR_XID属性が設定されていると、アプリケーションで、OCITransStart関数をタイムアウトとともにフラグOCI_TRANS_SESSIONLESS | OCI_TRANS_NEWを指定して実行することで、新しいセッションレス・トランザクションを開始できます。

OCI_TRANS_SESSIONLESSフラグにより、このリクエストが、XAブランチを開始するリクエストと区別されます。クライアントでの新しいセッションレス・トランザクションの開始は、事前コール・ピギーバックです。つまり、この開始リクエストは非同期であり、次のサーバー・ラウンドトリップが発生したときにサーバーに送信されサーバーによって処理されます。

OCISvcCtx *svchp;
OCIError *errhp;
...
ub4 timeout = 60;

/* start the transaction. this will be piggybacked on the subsequent round trip.
    */
OCITransStart(svchp, errhp, timeout, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);

ここでのtimeoutは、このセッションレス・トランザクションが一時停止されてから、サーバーによってこのトランザクションがロールバックされるまでの期間(秒)です。これは、トランザクションで無期限にデータベース・リソースが保持されること(行ロックなど)を防ぐための試みです。

サービス・コンテキスト・ハンドルのOCI_ATTR_TRANS属性が設定されていない場合、このコールは失敗し、OCI_INVALID_HANDLEが戻されます。OCIクライアント・ライブラリによって、最初に、トランザクション・ハンドルがサービス・コンテキスト・ハンドルの属性として存在するかどうかがチェックされます(OCIライブラリによってOCI_INVALID_HANDLEが戻される)。

そのフラグにOCI_TRANS_SESSIONLESSが含まれているが、OCI_TRANS_NEWOCI_TRANS_RESUMEも含まれていない場合は、エラー26213が戻されます。データベース・サーバーでセッションレス・トランザクションがサポートされていない場合は、エラー2027が戻されます。

状態 トランザクションが存在しない ローカル・トランザクション サーバーでセッションレス・トランザクションが開始された クライアントで、ライブラリで生成されたGTRIDでセッションレス・トランザクションが開始された クライアントで、ユーザーが提供したGTRIDでセッションレス・トランザクションが開始された グローバル・トランザクション
チェック なし なし 常にエラー26211 トランザクションがアクティブであり、生成されたGTRIDがまだ取得されていない場合は、エラー26204が戻されます。

事後コール・ピギーバック(例: 事後コールによる一時停止)が保留中の場合は、エラー26215を戻します。

内部GUID生成関数が失敗すると、エラー26205が戻されます。

事後コール・ピギーバック(たとえば、事後コールによる一時停止)が保留中の場合は、エラー26215を戻します。 なし

開始コールは、事前コール・ピギーバックとして記録されます。OCI_ATTR_XIDは、ピギーバックがデータベース・サーバーに送信される前に変更できず、それを設定しようとするとエラー26216が戻されます

25.2.5 アクティブ・セッションレス・トランザクションの一時停止

OCIクライアントで、アクティブなセッションレス・トランザクションを一時停止できます。一時停止が発生したときにセッションにトランザクションがない場合、一時停止プロシージャは操作不能となります。セッションにセッションレス・トランザクション以外のトランザクション(ローカル・トランザクションまたはXAトランザクション・ブランチ)がある場合は、エラーORA-26202が戻されます。アクティブなセッションレス・トランザクションの一時停止は、事前コール・ピギーバック、事後コール・ピギーバックまたはメイン・コール(つまり、それによってラウンドトリップが発生する)のどれかにできます。必要なオプションを示すフラグ・ビットを指定できます。

ノート:

事前コール・ピギーバックでエラーが発生した場合、メイン・コールは呼び出されません。メイン・コールでエラーが発生した場合、事後ピギーバックによる一時停止は呼び出されません。

例25-3 同期のOCITransDetach

アクティブなセッションレス・トランザクションをメイン・コールとして一時停止(そのトランザクションを同期的に一時停止)するには、次の例で示すように、OCITransDetach関数をコールします:

OCITransDetach(svchp, errhp, OCI_TRANS_SESSIONLESS | OCI_DEFAULT);

例25-4 事前コールのOCITransDetach

事前コール・ピギーバックによる一時停止(メイン・コールの前に次のサーバー・ラウンドトリップで一時停止)を発行するには、OCI_TRANS_SESSIONLESS | OCI_TRANS_PRE_CALL フラグを指定してOCITransDetach関数をコールします。

次の例では、トランザクションが、OCIPing()コールの間にラウンドトリップで一時停止されます。

OCITransDetach(svchp, errhp, OCI_TRANS_SESSIONLESS | OCI_TRANS_PRE_CALL);
OCIPing(svchp, errhp, OCI_DEFAULT);

例25-5 事後コールのOCITransDetach

事後コール・ピギーバックによる一時停止(メイン・コールの後に次のサーバー・ラウンドトリップで一時停止)を発行するには、次の例で示すように、OCI_TRANS_SESSIONLESS | OCI_TRANS_POST_CALLフラグを指定してOCITransDetach関数をコールします:

OCITransDetach(svchp, errhp, OCI_TRANS_SESSIONLESS | OCI_TRANS_POST_CALL);
OCIPing(svchp, errhp, OCI_DEFAULT);

ノート:

これは、サーバーへの最後のラウンドトリップがわかっている場合に役立ちます。

ノート:

事後コールによる一時停止は、開始トランザクションがピギーバックされるのと同じラウンドトリップでピギーバックできます。結果として、セッションレス・トランザクションのコンテキストで実行される単一の文は、単一のサーバー・ラウンドトリップで実行できます。

例25-6 事後コールのOCITransDetach

次の例では、OCIStmtExecute()が正常に実行されると、GTRID my_Flex_txn3で特定されたトランザクションが自動的に一時停止されます:

/* obtaining a service context handle from session pool */
OCISessionGet (envhp, errhp, &svchp, authInfop, poolName, poolNameLen, NULL, 0,
               NULL, NULL, NULL, OCI_SESSGET_SPOOL | OCI_SESSGET_PURITY_NEW);
OCIAttrSet (svchp, OCI_HTYPE_SVCCTX, txnhp, 0, OCI_ATTR_TRANS, errhp);
 
memcpy(xidp->data, "my_Flex_txn3", strlen("my_Flex_txn3"));
xidp->gtrid_length = strlen("my_Flex_txn3");
OCIAttrSet(txnhp, OCI_HTYPE_TRANS, &xidp, sizeof(XID), OCI_ATTR_XID, errhp);
OCITransStart(svchp, errhp, 60, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);
 
// Ask a post-call suspend
OCITransDetach(svchp, errhp, OCI_TRANS_SESSIONLESS | OCI_POST_CALL);
 
// Do the DML
OCIStmtPrepare(…); /* insert into mytab1(c1, c2) values (1, 1); */
OCIStmtBindByPos(…);
OCIStmtExecute(…);   /* Server suspends the transaction after this DML is executed. */
一時停止コールがサーバーに送信される前(同期の場合)または記録される前(事前コール・ピギーバックまたは事後コール・ピギーバックの場合)に、OCIによって次のことがチェックされます:
  • サービス・コンテキスト・ハンドルの属性OCI_ATTR_TRANSが、有効なトランザクション・ハンドルに設定されていない場合は、OCITransDetach関数でOCI_INVALID_HANDLEが戻されます。
  • このフラグにOCI_TRANS_SESSIONLESSが含まれているが、OCI_DEFAULTOCI_TRANS_PRE_CALLまたはOCI_TRANS_POST_CALLのどれも含まれていない場合は、エラー26214が戻されます。
  • サーバーでセッションレス・トランザクションがサポートされている場合は、エラー26207が戻されます。
  • 以前の、事後コールによる一時停止が、記録されているがまだサーバーに送信されていない場合は、エラー26215が発生します。これは、事前コールによる一時停止が呼び出されたときのみ適用されます。
状態 トランザクションが存在しない ローカル・トランザクション サーバーでセッションレス・トランザクションが開始された クライアントで、ライブラリで生成されたGTRIDでセッションレス・トランザクションが開始された クライアントで、ユーザーが提供したGTRIDでセッションレス・トランザクションが開始された XAトランザクション・ブランチ
チェック なし なし 常にエラー26211 トランザクションがアクティブであり、生成されたGTRIDがまだ取得されていない場合は、エラー26204が戻されます。事後コール・ピギーバック(例: 事後コールによる一時停止)が保留中の場合は、エラー26215を戻します。 事後コール・ピギーバック(たとえば、事後コールによる一時停止)が保留中の場合は、エラー26215を戻します。 なし

25.2.6 一時停止されたセッションレス・トランザクションの再開

一時停止中のセッションレス・トランザクションの再開は、セッションレス・トランザクションを開始するのと似ています。それら2つの間の相違は、OCIでセッションレス・トランザクションを再開するときに、OCITransStart関数でのOCI_TRANS_RESUMEフラグがOCI_TRANS_NEWフラグを置き換えられる点です。

サービス・コンテキスト・ハンドルのOCI_ATTR_TRANS属性は、トランザクション・ハンドルを指すように設定する必要があります。そのOCI_ATTR_XID属性は、再開するセッションレス・トランザクションのGTRIDを含むように設定する必要があります。OCITransStart関数をOCI_TRANS_SESSIONLESS | OCI_TRANS_RESUMEを指定して呼び出すと、OCI_ATTR_XIDで設定されているGTRIDで特定されたセッションレス・トランザクションが再開されます。クライアントでのセッションレス・トランザクションの再開は、事前コール・ピギーバックです。つまり、この再開リクエストは非同期であり、次のサーバー・ラウンドトリップでサーバーに送信されサーバーによって処理されます。

ub4 timeout = 20;
OCITransStart(svchp, errhp, timeout, OCI_TRANS_SESSIONLESS | OCI_TRANS_RESUME);

ここでのtimeout引数では、サーバーでそのトランザクションの再開が試みられる期間(秒単位)が決定されます。複数のセッションで同じデータベース・インスタンスに接続し、同じセッションレス・トランザクションを再開するようリクエストした場合、正常に再開できるのは一度に1つのみです。

再開コールを記録する前に、OCIによって次のチェックが実行されます:
  • 新しいセッションレス・トランザクションの開始と同様に、サービス・コンテキスト・ハンドルのOCI_ATTR_TRANS属性が設定されていない場合、このコールは失敗し、OCI_INVALID_HANDLEが戻されます。
  • このフラグ引数にOCI_TRANS_SESSIONLESSが含まれているが、OCI_TRANS_NEWもOCI_TRANS_RESUMEも含まれていない場合は、エラー26213が戻されます。
  • データベース・サーバーでセッションレス・トランザクションがサポートされていない場合は、エラー26207が戻されます。
  • トランザクション・ハンドルのOCI_ATTR_XID属性が設定されていない場合は、エラー26212が戻されます。
  • セッションレス・トランザクションが開始されると、データベース・サーバーがアクティブになり、エラー26211が戻されます。
  • OCIライブラリでセッションレス・トランザクションが開始されると、生成されたGTRIDがアクティブになります。そのようなGTRIDが取得されていない場合は、エラー26204が戻されます
  • 事後コールによる一時停止が記録されたがまだサーバーに送信されていない場合は、エラー26215が戻されます。

チェックに合格すると、OCIライブラリによって、この事前コール・ピギーバックによる再開のリクエストが記録されます。OCI_ATTR_XIDは、この事前コール・リクエストがサーバーによって処理されるまで変更できません。それを設定しようとすると、エラー26216が戻されます。

25.2.7 セッションレス・トランザクションのコミット

セッション内のアクティブなセッションレス・トランザクションをコミットするために、OCIStmtExecute()関数を使用してCOMMIT文がサーバーに発行されます。同様に、OCITransCommit()関数はOCIクライアントから実行されます。

次の例では、GTRID my_Flex_txn5で特定されたセッションレス・トランザクションを開始し、DMLを発行してそのトランザクションをコミットしています:

例25-7 OCITransCommit()を使用したコミット


OCISessionGet (envhp, errhp, &svchp, authInfop, poolName, poolNameLen, NULL, 0,
               NULL, NULL, NULL, OCI_SESSGET_SPOOL | OCI_SESSGET_PURITY_NEW);
OCIAttrSet (svchp, OCI_HTYPE_SVCCTX, txnhp, 0, OCI_ATTR_TRANS, errhp);
 
memcpy(xidp->data, "my_Flex_txn5", strlen("my_Flex_txn5"));
xidp->gtrid_length = strlen("my_Flex_txn5");
OCIAttrSet(txnhp, OCI_HTYPE_TRANS, &xidp, sizeof(XID), OCI_ATTR_XID, errhp);
OCITransStart(svchp, errhp, 60, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);
 /* Executes unit of work in the Sessionless transaction context */ 
OCITransCommit(svchp, errhp, OCI_DEFAULT);

例25-8 OCISessionRelease()を使用したコミット

既存の動作に従って、OCISessionReleaseによって、アクティブなセッションレス・トランザクションがコミットされます。次の例では、my_Flex_txn6で特定されたセッションレス・トランザクションがコミットされます:

/* start Sessionless transaction */
OCISessionGet (envhp, errhp, &svchp, authInfop, poolName, poolNameLen, NULL, 0, NULL,
               NULL, NULL, OCI_SESSGET_SPOOL | OCI_SESSGET_PURITY_NEW);
 
OCIAttrSet (svchp, OCI_HTYPE_SVCCTX, txnhp, 0, OCI_ATTR_TRANS, errhp);
 
memcpy(xidp->data, "my_Flex_txn6", strlen("my_Flex_txn6"));
xidp->gtrid_length = strlen("my_Flex_txn6");
OCIAttrSet(txnhp, OCI_HTYPE_TRANS, &xidp, sizeof(XID), OCI_ATTR_XID, errhp);
OCITransStart(svchp, errhp, 60, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);
/* done start Sessionless transaction */
/* Executes unit of work in the Sessionless transaction context */
 OCISessionRelease(svchp, errhp, 0, 0, OCI_DEFAULT); 
/* Commits the Sessionless transaction */

25.2.8 セッションレス・トランザクションのロールバック

セッション内のアクティブなセッションレス・トランザクションをロールバックするには、OCIStmtExecute()関数を使用してROLLBACK文をサーバーに発行します。同様に、クライアントからのOCITransRollback()関数の実行が成功すると、セッション内のアクティブなセッションレス・トランザクションがロールバックされます。次の例では、my_Flex_txn8で特定されたセッションレス・トランザクションを開始し、DML文を発行して、作業単位を実行しています。

例25-9 OCITransRollback()を使用したロールバック

OCIクライアントからOCITransRollback()関数を実行します。

/* start Sessionless transaction */
OCISessionGet (envhp, errhp, &svchp, authInfop, poolName, poolNameLen, NULL, 0, NULL,
               NULL, NULL, OCI_SESSGET_SPOOL | OCI_SESSGET_PURITY_NEW);
 
OCIAttrSet (svchp, OCI_HTYPE_SVCCTX, txnhp, 0, OCI_ATTR_TRANS, errhp);
 
char gtrid = "my_Flex_txn8";
memcpy(xidp->data, gtrid, strlen(gtrid));
xidp->gtrid_length = strlen(gtrid);
OCIAttrSet(txnhp, OCI_HTYPE_TRANS, &xidp, sizeof(XID), OCI_ATTR_XID, errhp);
OCITransStart(svchp, errhp, 60, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);
/* done start Sessionless transaction */
/* Executes unit of work in the Sessionless transaction context */ 
OCITransRollback(svchp, errhp, OCI_DEFAULT);

例25-10 OCIRequestEnd()を使用したロールバック

次の例では、GTRID my_Flex_txn9で特定されたトランザクションが、OCIRequestEnd()が正常に実行された後にロールバックされます:


OCISessionGet (envhp, errhp, &svchp, authInfop, poolName, poolNameLen, NULL, 0, NULL,
               NULL, NULL, OCI_SESSGET_SPOOL | OCI_SESSGET_PURITY_NEW);
 
OCIAttrSet (svchp, OCI_HTYPE_SVCCTX, txnhp, 0, OCI_ATTR_TRANS, errhp);
 
char gtrid = "my_Flex_txn9";
memcpy(xidp->data, gtrid, strlen(gtrid));
xidp->gtrid_length = strlen(gtrid);
OCIAttrSet(txnhp, OCI_HTYPE_TRANS, &xidp, sizeof(XID), OCI_ATTR_XID, errhp);
/* start Sessionless transaction */
OCITransStart(svchp, errhp, 60, OCI_TRANS_SESSIONLESS | OCI_TRANS_NEW);
 
OCIRequestBegin(…);
/* Executes unit of work in the Sessionless transaction context */
OCIRequestEnd(…); /* Rolled back the Sessionless transaction */