27.7 トランザクション関数

トランザクション関数をリストし、説明します。

表27-6は、この項で説明しているトランザクション関数を示しています。

表27-6 トランザクション関数

関数 用途

OCITransStart()

サービス・コンテキスト上のトランザクションを開始します。

OCITransDetach()

サービス・コンテキストからトランザクションを連結解除します。

OCITransCommit()

サービス・コンテキスト上のトランザクションをコミットします。

OCITransRollback()

トランザクションをロールバックします。

OCITransForget()

準備したグローバル・トランザクションを放棄します。

OCITransMultiPrepare()

単一セルに複数のブランチがあるトランザクションを準備します。

OCITransPrepare()

グローバル・トランザクションをコミットのために準備します。

27.7.1 OCITransStart()

トランザクションの開始を設定します。

用途

トランザクションの開始を設定します。Oracleリリース23ai以降、OCITransStart()関数は、セッションレス・トランザクションの開始および再開を処理するように拡張されています。

構文

sword OCITransStart ( OCISvcCtx    *svchp, 
                      OCIError     *errhp, 
                      uword         timeout,
                      ub4           flags );

パラメータ

svchp (IN/OUT)

サービス・コンテキスト・ハンドルです。flagsパラメータに新規トランザクションの開始が指定されている場合は、このコールの終了時点で、サービス・コンテキスト・ハンドル内のトランザクション・コンテキストが初期化されます。

errhp (IN/OUT)

OCIエラー・ハンドルです。エラーがある場合は、errに記録され、OCI_ERRORが戻されます。OCIErrorGet()のコールによって診断情報を取得できます。

timeout (IN)

OCI_TRANS_RESUMEが指定されたときに、トランザクションが再開できるようになるまで待機する時間(秒)です。OCI_TRANS_NEWが指定されると、timeoutパラメータの指示する秒数間、非活動状態が続いたトランザクションは、システムによって自動的に終了します。グローバル・トランザクション・ブランチまたはセッションレス・トランザクションは、OCITransDetach()を使用して連結解除(グローバル・トランザクション・ブランチ)または一時停止(セッションレス・トランザクション)してからOCITransStart()を使用して再開するまでの間に非アクティブになります。

  • OCI_TRANS_RESUMEが指定され、OCI_TRANS_SESSIONLESSが指定されていないときに、トランザクションが再開できるようになるまで待機する時間(秒)です。
  • OCI_TRANS_RESUMEOCI_TRANS_SESSIONLESSが指定されている場合、タイムアウトは使用されません。
flags (IN)
トランザクション・フラグは、次のように分類されます:
  • トランザクション・タイプ: このカテゴリに指定できるフラグのタイプは1つのみです。フラグが指定されていない場合は、デフォルトで、密結合グローバル・トランザクション(OCI_TRANS_TIGHT)が開始されます。
    • OCI_TRANS_LOOSE: 疎結合グローバル・トランザクション・ブランチを指定します。
    • OCI_TRANS_TIGHT: 密結合グローバル・トランザクション・ブランチを指定します。
    • OCI_TRANS_SESSIONLESS: セッションレス・トランザクションを指定します。
  • 開始操作:
    • トランザクション・タイプOCI_TRANS_LOOSEまたはOCI_TRANS_TIGHTに設定した場合、またはデフォルト・タイプ(OCI_TRANS_TIGHT)を使用する場合、開始操作はOCI_TRANS_NEWOCI_TRANS_JOINOCI_TRANS_RESUMEまたはOCI_TRANS_PROMOTEのいずれかになります。開始操作を指定しない場合のデフォルト・フラグはOCI_TRANS_NEWです。
    • トランザクション・タイプOCI_TRANS_SESSIONLESSに設定した場合、開始操作はOCI_TRANS_NEWまたはOCI_TRANS_RESUMEのいずれかになります。デフォルト値がないため、開始操作を指定する必要があります。
    • OCI_TRANS_NEW: 新規グローバル・トランザクション・ブランチまたは新規セッションレス・トランザクションを開始します。これを使用してグローバル・トランザクションを開始すると、デフォルトで、密結合かつ移行可能なブランチが開始されます。
    • OCI_TRANS_JOIN: 既存のグローバル・トランザクションに参加します。
    • OCI_TRANS_RESUME: グローバル・トランザクション・ブランチまたはセッションレス・トランザクションを再開します。
    • OCI_TRANS_PROMOTE: ローカル・トランザクションからグローバル・トランザクションに昇格します。
  • 分離:
    • トランザクション・タイプOCI_TRANS_LOOSEまたはOCI_TRANS_TIGHTに設定した場合、またはデフォルト・タイプ(OCI_TRANS_TIGHT)を使用する場合は、分離フラグをOCI_TRANS_READONLYOCI_TRANS_READWRITEまたはOCI_TRANS_SERIALIZABLEに設定できます。分離フラグが指定されていない場合、トランザクションはOCI_TRANS_READWRITE分離レベルで開始されます。
    • トランザクション・タイプOCI_TRANS_SESSIONLESSに設定すると、分離フラグは使用されません。トランザクションは常にOCI_TRANS_READWRITE分離レベルで開始されます。
    • OCI_TRANS_READONLY: 読取り専用トランザクションを開始します。
    • OCI_TRANS_READWRITE: 読取り/書込みトランザクションを開始します。
    • OCI_TRANS_SERIALIZABLE: シリアライズ可能トランザクションを開始します。
  • その他のフラグ:
    • OCI_TRANS_NOMIGRATE
    • OCI_TRANS_SEPARABLE: 各コール後にトランザクションを分離します。このフラグにより、標準のトランザクションを使用してトランザクションが開始されたという警告が示されます。リリース9.0.1のサーバーでは、分離されたトランザクションはサポートされていません。
    • OCI_TRANS_OTSRESUME
エラー・メッセージ: コードまたはトランザクション・サービスにエラーがある場合は、エラー・メッセージが表示されます。このエラーは、すでに開始されていたトランザクションで処理を試行したことを示します。エラー・メッセージは、次のいずれかの条件を示します:
  • APIに渡されたフラグの組合せが無効です
  • 無効なXIDが使用されています
  • セッションにはすでにアクティブなローカル・トランザクションがあります
  • セッションにグローバル・トランザクションがあり、XIDで指定された新規トランザクションを開始するために接続解除できませんでした
  • グローバル・トランザクションの開始または再開中にタイムアウトが発生しました

コメント

この関数は、グローバル・トランザクション、シリアライズ可能トランザクションまたはセッションレス・トランザクションの開始を設定します。flagsパラメータに新規トランザクションの開始が指定されている場合は、このコールの終了時点で、サービス・コンテキスト・ハンドルに現在対応付けられているトランザクション・コンテキストが初期化されます。

コールを使用してグローバル・トランザクションを制御する場合は、トランザクション識別子(XID構造体)をトランザクション・ハンドルのOCI_ATTR_XID属性として設定する必要があります(そのポインタはサービス・コンテキスト・ハンドルsvchpOCI_ATTR_TRANS属性として設定されます)。このコールを使用して新しいセッションレス・トランザクションを開始する場合は、OCI_ATTR_XID属性を、新しいトランザクションのグローバル・トランザクションID (GTRID)を指定するトランザクション識別子(XID構造体)に設定するか、生成されたGTRIDをリクエストするためにNULLポインタに設定できます。セッションレス・トランザクションを再開するためにコールを使用する場合。OCI_ATTR_XID属性は、再開するトランザクションのグローバル・トランザクションID (GTRID)を指定するトランザクション識別子(XID構造)に設定する必要があります。

次のコード例とそれに続くコード例では、OCIトランザクション・コールを使用してグローバルなトランザクションを操作する方法を説明します。次のコード例に示すような、様々なブランチで動作するシングル・セッションの概念は、図9-2で示しています。

様々なブランチで動作するシングル・セッションでのOCITransStart()の使用

int main()
{
  OCIEnv *envhp;
  OCIServer *srvhp;
  OCIError *errhp;
  OCISvcCtx *svchp;
  OCISession *usrhp;
  OCIStmt *stmthp1, *stmthp2;
  OCITrans *txnhp1, *txnhp2;
  void      *tmp;
  XID gxid;
  text sqlstmt[128];

  OCIEnvCreate(&envhp, OCI_DEFAULT, (void  *)0, 0, 0, 0,
        (size_t)0, (void  *)0);

  OCIHandleAlloc( (void  *) envhp, (void  **) &errhp, (ub4)
                OCI_HTYPE_ERROR, 52, (void  **) &tmp);
  OCIHandleAlloc( (void  *) envhp, (void  **) &srvhp, (ub4)
               OCI_HTYPE_SERVER, 52, (void  **) &tmp);

  OCIServerAttach( srvhp, errhp, (text *) 0, (sb4) 0, (ub4) OCI_DEFAULT);

  OCIHandleAlloc( (void  *) envhp, (void  **) &svchp, (ub4) OCI_HTYPE_SVCCTX,
                52, (void  **) &tmp);

  OCIHandleAlloc((void  *)envhp, (void  **)&stmthp1, OCI_HTYPE_STMT, 0, 0);
  OCIHandleAlloc((void  *)envhp, (void  **)&stmthp2, OCI_HTYPE_STMT, 0, 0);

  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)srvhp, 0,
                  OCI_ATTR_SERVER, errhp);

  /* set the external name and internal name in server handle */
  OCIAttrSet((void  *)srvhp, OCI_HTYPE_SERVER, (void  *) "demo", 0,
                  OCI_ATTR_EXTERNAL_NAME, errhp);
  OCIAttrSet((void  *)srvhp, OCI_HTYPE_SERVER, (void  *) "txn demo", 0,
                          OCI_ATTR_INTERNAL_NAME, errhp);

  /* allocate a user context handle */
  OCIHandleAlloc((void  *)envhp, (void  **)&usrhp, (ub4) OCI_HTYPE_SESSION,
                (size_t) 0, (void  **) 0);

  OCIAttrSet((void  *)usrhp, (ub4)OCI_HTYPE_SESSION, (void  *)"HR",
             (ub4)strlen("HR"), OCI_ATTR_USERNAME, errhp);
  OCIAttrSet((void  *)usrhp, (ub4)OCI_HTYPE_SESSION, (void  *)"HR",
             (ub4)strlen("HR"),OCI_ATTR_PASSWORD, errhp);

  OCISessionBegin (svchp, errhp, usrhp, OCI_CRED_RDBMS, 0);

  OCIAttrSet((void  *)svchp, (ub4)OCI_HTYPE_SVCCTX,
                (void  *)usrhp, (ub4)0, OCI_ATTR_SESSION, errhp);

  /* allocate transaction handle 1 and set it in the service handle */
  OCIHandleAlloc((void  *)envhp, (void  **)&txnhp1,  OCI_HTYPE_TRANS, 0, 0);
  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp1, 0,
                          OCI_ATTR_TRANS, errhp);

  /* start a transaction with global transaction id = [1000, 123, 1] */
  gxid.formatID = 1000; /* format id = 1000 */
  gxid.gtrid_length = 3; /* gtrid = 123 */
  gxid.data[0] = 1; gxid.data[1] = 2; gxid.data[2] = 3;
  gxid.bqual_length = 1; /* bqual = 1 */
  gxid.data[3] = 1;

  OCIAttrSet((void  *)txnhp1, OCI_HTYPE_TRANS, (void  *)&gxid, sizeof(XID),
                          OCI_ATTR_XID, errhp);

  /* start global transaction 1 with 60-second time to live when detached */
  OCITransStart(svchp, errhp, 60, OCI_TRANS_NEW);

  /* update hr.employees employee_id=7902, increment salary */
  sprintf((char *)sqlstmt, "UPDATE EMPLOYEES SET SALARY = SALARY + 1 \
                                           WHERE EMPLOYEE_ID = 7902");
  OCIStmtPrepare(stmthp1, errhp, sqlstmt, strlen((char *)sqlstmt),
                 OCI_NTV_SYNTAX, 0);
  OCIStmtExecute(svchp, stmthp1, errhp, 1, 0, 0, 0, 0);

  /* detach the transaction */
  OCITransDetach(svchp, errhp, 0);

  /* allocate transaction handle 2 and set it in the service handle */
  OCIHandleAlloc((void  *)envhp, (void  **)&txnhp2,  OCI_HTYPE_TRANS, 0, 0);

  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp2, 0,
                          OCI_ATTR_TRANS, errhp);

  /* start a transaction with global transaction id = [1000, 124, 1] */
  gxid.formatID = 1000; /* format id = 1000 */
  gxid.gtrid_length = 3; /* gtrid = 124 */
  gxid.data[0] = 1; gxid.data[1] = 2; gxid.data[2] = 4;
  gxid.bqual_length = 1; /* bqual = 1 */
  gxid.data[3] = 1;

  OCIAttrSet((void  *)txnhp2, OCI_HTYPE_TRANS, (void  *)&gxid, sizeof(XID),
                          OCI_ATTR_XID, errhp);

  /* start global transaction 2 with 90 second time to live when detached */
  OCITransStart(svchp, errhp, 90, OCI_TRANS_NEW);

  /* update hr.employees employee_id=7934, increment salary */
  sprintf((char *)sqlstmt, "UPDATE EMPLOYEES SET SALARY = SALARY + 1 \
                                            WHERE EMPLOYEE_ID = 7934");
  OCIStmtPrepare(stmthp2, errhp, sqlstmt, strlen((char *)sqlstmt),
                 OCI_NTV_SYNTAX, 0);
  OCIStmtExecute(svchp, stmthp2, errhp, 1, 0, 0, 0, 0);

  /* detach the transaction */
  OCITransDetach(svchp, errhp, 0);

  /* Resume transaction 1, increment salary and commit it */
  /* Set transaction handle 1 into the service handle */
  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp1, 0,
                          OCI_ATTR_TRANS, errhp);

  /* attach to transaction 1, wait for 10 seconds if the transaction is busy */
  /* The wait is clearly not required in this example because no other */
  /* process/thread is using the transaction. It is only for illustration */
  OCITransStart(svchp, errhp, 10, OCI_TRANS_RESUME);
  OCIStmtExecute(svchp, stmthp1, errhp, 1, 0, 0, 0, 0);
  OCITransCommit(svchp, errhp, (ub4) 0);

  /* attach to transaction 2 and commit it */
  /* set transaction handle2 into the service handle */
  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp2, 0,
                          OCI_ATTR_TRANS, errhp);
  OCITransCommit(svchp, errhp, (ub4) 0);
}

同じトランザクションを共有する複数のブランチで動作するシングル・セッションでのOCITransStart()の使用

int main()
{
  OCIEnv *envhp;
  OCIServer *srvhp;
  OCIError *errhp;
  OCISvcCtx *svchp;
  OCISession *usrhp;
  OCIStmt *stmthp;
  OCITrans *txnhp1, *txnhp2;
  void      *tmp;
  XID gxid;
  text sqlstmt[128];

  OCIEnvCreate(&envhp, OCI_DEFAULT, (void  *)0, 0, 0, 0,
        (size_t)0, (void  *)0);

  OCIHandleAlloc( (void  *) envhp, (void  **) &errhp, (ub4) OCI_HTYPE_ERROR,
                52, (void  **) &tmp);
  OCIHandleAlloc( (void  *) envhp, (void  **) &srvhp, (ub4) OCI_HTYPE_SERVER,
                52, (void  **) &tmp);

  OCIServerAttach( srvhp, errhp, (text *) 0, (sb4) 0, (ub4) OCI_DEFAULT);

  OCIHandleAlloc( (void  *) envhp, (void  **) &svchp, (ub4) OCI_HTYPE_SVCCTX,
                52, (void  **) &tmp);

  OCIHandleAlloc((void  *)envhp, (void  **)&stmthp, OCI_HTYPE_STMT, 0, 0);

  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)srvhp, 0,
                  OCI_ATTR_SERVER, errhp);

  /* set the external name and internal name in server handle */
  OCIAttrSet((void  *)srvhp, OCI_HTYPE_SERVER, (void  *) "demo", 0,
                  OCI_ATTR_EXTERNAL_NAME, errhp);
  OCIAttrSet((void  *)srvhp, OCI_HTYPE_SERVER, (void  *) "txn demo2", 0,
                  OCI_ATTR_INTERNAL_NAME, errhp);

  /* allocate a user context handle */
  OCIHandleAlloc((void  *)envhp, (void  **)&usrhp, (ub4) OCI_HTYPE_SESSION,
                (size_t) 0, (void  **) 0);

  OCIAttrSet((void  *)usrhp, (ub4)OCI_HTYPE_SESSION, (void  *)"HR",
             (ub4)strlen("HR"), OCI_ATTR_USERNAME, errhp);
  OCIAttrSet((void  *)usrhp, (ub4)OCI_HTYPE_SESSION, (void  *)"HR",
             (ub4)strlen("HR"),OCI_ATTR_PASSWORD, errhp);

  OCISessionBegin (svchp, errhp, usrhp, OCI_CRED_RDBMS, 0);

  OCIAttrSet((void  *)svchp, (ub4)OCI_HTYPE_SVCCTX,
                (void  *)usrhp, (ub4)0, OCI_ATTR_SESSION, errhp);

  /* allocate transaction handle 1 and set it in the service handle */
  OCIHandleAlloc((void  *)envhp, (void  **)&txnhp1,  OCI_HTYPE_TRANS, 0, 0);
  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp1, 0,
                          OCI_ATTR_TRANS, errhp);

  /* start a transaction with global transaction id = [1000, 123, 1] */
  gxid.formatID = 1000; /* format id = 1000 */
  gxid.gtrid_length = 3; /* gtrid = 123 */
  gxid.data[0] = 1; gxid.data[1] = 2; gxid.data[2] = 3;
  gxid.bqual_length = 1; /* bqual = 1 */
  gxid.data[3] = 1;

  OCIAttrSet((void  *)txnhp1, OCI_HTYPE_TRANS, (void  *)&gxid, sizeof(XID),
                          OCI_ATTR_XID, errhp);

  /* start global transaction 1 with 60-second time to live when detached */
  OCITransStart(svchp, errhp, 60, OCI_TRANS_NEW);

  /* update hr.employees employee_id=7902, increment salary */
  sprintf((char *)sqlstmt, "UPDATE EMPLOYEES SET SALARY = SALARY + 1 \
                                            WHERE EMPLOYEE_ID = 7902");
  OCIStmtPrepare(stmthp, errhp, sqlstmt, strlen((char *)sqlstmt),
                 OCI_NTV_SYNTAX, 0);
  OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, 0);

  /* detach the transaction */
  OCITransDetach(svchp, errhp, 0);

  /* allocate transaction handle 2 and set it in the service handle */
  OCIHandleAlloc((void  *)envhp, (void  **)&txnhp2,  OCI_HTYPE_TRANS, 0, 0);
  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp2, 0,
                          OCI_ATTR_TRANS, errhp);

  /* start a transaction with global transaction id = [1000, 123, 2] */
  /* The global transaction is tightly coupled with earlier transactions */
  /* There is not much practical value in doing this but the example */
  /* illustrates the use of tightly coupled transaction branches. */
  /* In a practical case, the second transaction that tightly couples with */
  /* the first can be executed from a different process/thread. */

  gxid.formatID = 1000; /* format id = 1000 */
  gxid.gtrid_length = 3; /* gtrid = 123 */
  gxid.data[0] = 1; gxid.data[1] = 2; gxid.data[2] = 3;
  gxid.bqual_length = 1; /* bqual = 2 */
  gxid.data[3] = 2;

  OCIAttrSet((void  *)txnhp2, OCI_HTYPE_TRANS, (void  *)&gxid,
sizeof(XID), OCI_ATTR_XID, errhp);

  /* start global transaction 2 with 90-second time to live when detached */
  OCITransStart(svchp, errhp, 90, OCI_TRANS_NEW);

  /* update hr.employees employee_id=7902, increment salary */
  /* This is possible even if the earlier transaction has locked this row */
  /* because the two global transactions are tightly coupled */
  OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, 0);

  /* detach the transaction */
  OCITransDetach(svchp, errhp, 0);

  /* Resume transaction 1 and prepare it. This returns */
  /* OCI_SUCCESS_WITH_INFO because all branches except the last branch */
  /* are treated as read-only transactions for tightly coupled transactions */

  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp1, 0,
                          OCI_ATTR_TRANS, errhp);
  if (OCITransPrepare(svchp, errhp, (ub4) 0) == OCI_SUCCESS_WITH_INFO)
  {
    text errbuf[512];
    ub4 buflen;
    sb4 errcode;

    OCIErrorGet ((void  *) errhp, (ub4) 1, (text *) NULL, &errcode,
    errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR);
    printf("OCITransPrepare - %s\n", errbuf);
  }

  /* attach to transaction 2 and commit it */
  /* set transaction handle2 into the service handle */
  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)txnhp2, 0,
                          OCI_ATTR_TRANS, errhp);
  OCITransCommit(svchp, errhp, (ub4) 0);
}

関連トピック

27.7.2 OCITransDetach()

グローバル・トランザクションを連結解除するか、アクティブなセッションレス・トランザクションを一時停止します。

用途

グローバル・トランザクションの連結を解除します。Oracleリリース23ai以降、この関数は、アクティブなセッションレス・トランザクションを一時停止するように拡張されています。

構文

sword OCITransDetach ( OCISvcCtx    *svchp,
                       OCIError     *errhp,
                       ub4           flags );

パラメータ

svchp (IN)

サービス・コンテキスト・ハンドルです。

errhp (IN)

エラー発生時の診断情報のためにOCIErrorGet()に渡すエラー・ハンドルです。

flags (IN)

グローバル・トランザクションを接続解除する際、このパラメータにOCI_DEFAULTを渡す必要があります。

アクティブなセッションレス・トランザクションを一時停止する際、次のフラグのいずれかとともにOCI_TRANS_SESSIONLESSを渡す必要があります:
  • OCI_DEFAULT: 一時停止コールは即時に実行されます。
  • OCI_TRANS_PRE_CALL: 事前コール一時停止をリクエストします。一時停止は、次のサーバー・ラウンドトリップに接続され、メイン・コールの前に実行されます。
  • OCI_TRANS_POST_CALL: 事後コール一時停止をリクエストします。一時停止は、次のサーバー・ラウンドトリップに接続され、メイン・コールの後に実行されます。
ラウンドトリップ・コールは、ゼロ以外のサーバー・ラウンドトリップを引き起こすコールです。

コメント

コールを使用してグローバル・トランザクションを接続解除すると、このコールの最後にトランザクションは非アクティブになります。セッションレス・トランザクションを一時停止するためにコールが使用されている場合、一時停止はただちに発生するか、次のサーバー・ラウンドトリップに接続してメイン・コールの前に実行するか(事前コール一時停止)、次のサーバー・ラウンドトリップに接続してメイン・コールの後に実行するか(事後コール・ピギーバック)のいずれかです。

このトランザクションは、後でOCITransStart()をコールし、フラグOCI_TRANS_RESUMEの値を指定することで再開できます。

トランザクションが連結解除または一時停止されると、トランザクションの開始時にOCITransStart()timeoutパラメータに指定された値を使用して、サーバーのPMONプロセスによって削除されるまでブランチを非アクティブにしておける時間が判断されます。

ノート:

トランザクションが同一の認可を持っている場合、トランザクションは、その連結を解除したセッションまたはプロセスとは異なるセッションまたはプロセスによって再開できます。トランザクションが実際に開始される前にこの関数がコールされると、この関数は何も行いません。

OCITransDetach()の使用方法を説明するコード例については、OCITransStart()の例の項を参照してください。

関連トピック

27.7.3 OCITransCommit()

指定のサービス・コンテキストに対応付けられたトランザクションをコミットします。

用途

指定のサービス・コンテキストに対応付けられたトランザクションをコミットします。

構文

sword OCITransCommit ( OCISvcCtx    *svchp,
                       OCIError     *errhp,
                       ub4           flags );

パラメータ

svchp (IN)

サービス・コンテキスト・ハンドルです。

errhp (IN)

エラー発生時の診断情報のためにOCIErrorGet()に渡すエラー・ハンドルです。

flags (IN)

グローバル・トランザクションの1フェーズ・コミットを最適化するためのフラグです。

OCI_DEFAULT - トランザクションが分散型でない場合(セッションレス・トランザクションを含む)、flagパラメータのパラメータは無視され、その値としてOCI_DEFAULTを渡すことができます。

OCI_TRANS_TWOPHASE- 2フェーズ・コミットでは、グローバル・トランザクションを管理しているOCIアプリケーションは、flagsに対してこの値を渡す必要があります。デフォルトは1フェーズ・コミットです。

OCI_TRANS_WRITEIMMED- (インメモリー)REDOバッファをオンラインREDOログに書き込むためのI/OがLGWR (バックグラウンドのログ・ライター・プロセス)によって開始されます。IMMEDIATEとは、メッセージをLGWRに送信してLGWRでメッセージを即時に処理し、トランザクションのREDOバッファを即時に書き出すことを示します。

OCI_TRANS_WRITEBATCH- トランザクションのインメモリーREDOバッファをオンラインREDOログに書き込むためのI/OはLGWRによって発行されません。BATCHは、LGWRがREDOバッファをバッチ処理してからバッチ全体に対してI/Oを開始することを示します。BATCHIMMEDIATEの両方を指定するとエラーが発生します。デフォルトはIMMEDIATEです。

OCI_TRANS_WRITEWAIT - これは、コミットのREDOバッファをオンラインREDOログに書き込むようLGWRに要求し、書き込まれるまではコミットを待機させます。WAITとは、トランザクションに対応するインメモリーREDOバッファが永続オンラインREDOログに書き込まれて初めてコミットが終了することを示します。

OCI_TRANS_WRITENOWAIT- これは、コミットのREDOバッファをオンラインREDOログに書き込むようLGWRに要求しますが、バッファがオンラインREDOログに書き込まれるのを待たずにコミットは終了します。NOWAITとは、インメモリーREDOバッファをオンラインREDOログにフラッシュせずにコミットが終了することを示します。WAITNOWAITの両方を指定するとエラーが発生します。デフォルトはWAITです。

ノート:

OCI_TRANS_WRITENOWAITを使用すると、警告なしでトランザクションが消失する可能性があります。トランザクションの消失は、強制停止、強制起動、およびインスタンス障害やノード障害によって、警告なしに発生します。Oracle RACシステムでは、非同期にコミットされた場合、他のインスタンスでその変更を即時に読み取れない場合があります。

これら最後の4つのオプションは、分散型でないトップレベルのトランザクションのコミットのみに影響し、外部協調分散トランザクションでは無視されます。これらのオプションは、指定されている制限内容に応じてOR演算子を使用して結合できます。

コメント

サービス・コンテキストに現在対応付けられているトランザクションをコミットします。複数のトランザクションを定義している場合、この関数は、サービス・コンテキストに現在対応付けられているトランザクションを処理します。トランザクションのタイプに応じて、この関数の動作は次のようになります:
  • データベースの変更時に作成される暗黙的ローカル・トランザクションのみを処理している場合は、その暗黙的トランザクションがコミットされます。
  • アプリケーションがセッションレス・トランザクションを処理している場合、そのセッションレス・トランザクションがコミットされます。
  • アプリケーションをオブジェクト・モードで実行している場合は、このトランザクションに対してオブジェクト・キャッシュで変更または更新されたオブジェクトもフラッシュされ、コミットされます。
  • トランザクションがサーバーによるコミットが不可能なグローバル・トランザクションである場合、このコールは、トランザクションの状態をデータベースから取得します。その後、エラー・ハンドルを使用してユーザーに返されます。

正常な状況では、OCITransCommit()は、トランザクションがコミットされたかロールバックされたかを示す状態を戻します。グローバル・トランザクションでは、トランザクションがインダウトの状態、つまり、コミットも終了もされていない状態の場合もあり得ます。このような場合、OCITransCommit()は、トランザクションの状態をサーバーから取得しようとします。

次のコード例は、「単純なローカル・トランザクション」に記述されている単純なローカル・トランザクションの使用方法を説明しています。

単純なローカル・トランザクションでのOCITransCommit()の使用

int main()
{
  OCIEnv *envhp;
  OCIServer *srvhp;
  OCIError *errhp;
  OCISvcCtx *svchp;
  OCIStmt *stmthp;
  void      *tmp;
  text sqlstmt[128];

  OCIEnvCreate(&envhp, OCI_DEFAULT, (void  *)0, 0, 0, 0,
        (size_t)0, (void  *)0);

  OCIHandleAlloc( (void  *) envhp, (void  **) &errhp, (ub4) OCI_HTYPE_ERROR,
                (size_t)0, (void  **) 0);
  OCIHandleAlloc( (void  *) envhp, (void  **) &srvhp, (ub4) OCI_HTYPE_SERVER,
                (size_t)0, (void  **) 0);

  OCIServerAttach( srvhp, errhp, (text *) 0, (sb4) 0, (ub4) OCI_DEFAULT);

  OCIHandleAlloc( (void  *) envhp, (void  **) &svchp, (ub4) OCI_HTYPE_SVCCTX,
                (size_t)0, (void  **) 0);

  OCIHandleAlloc((void  *)envhp, (void  **)&stmthp, OCI_HTYPE_STMT, 0, 0);

  OCIAttrSet((void  *)svchp, OCI_HTYPE_SVCCTX, (void  *)srvhp, 0,
                  OCI_ATTR_SERVER, errhp);

  OCILogon(envhp, errhp, &svchp, (text *)"HR", strlen("HR"),
                 (text *)"HR", strlen("HR"), 0, 0);

  /* update hr.employees employee_id=7902, increment salary */
  sprintf((char *)sqlstmt, "UPDATE EMPLOYEES SET SALARY = SALARY + 1 \
                                            WHERE  EMPLOYEE_ID = 7902");

  OCIStmtPrepare(stmthp, errhp, sqlstmt, strlen((char *)sqlstmt),
                 OCI_NTV_SYNTAX, 0);
  OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, 0);
  OCITransCommit(svchp, errhp, (ub4) 0);

  /* update hr.employees employee_id=7902, increment salary again, but rollback */
  OCIStmtExecute(svchp, stmthp, errhp, 1, 0, 0, 0, 0);
  OCITransRollback(svchp, errhp, (ub4) 0);
}

関連トピック

27.7.4 OCITransRollback()

カレント・トランザクションをロールバックします。

用途

カレント・トランザクションをロールバックします。

構文

sword OCITransRollback ( void         *svchp, 
                         OCIError     *errhp,
                         ub4           flags );

パラメータ

svchp (IN)

サービス・コンテキスト・ハンドルです。サービス・コンテキスト・ハンドル内に現在設定されているトランザクションがロールバックされます。

errhp (IN)

エラー発生時の診断情報のためにOCIErrorGet()に渡すエラー・ハンドルです。

flags (IN)

このパラメータ用に値OCI_DEFAULTを渡す必要があります。

コメント

カレント・トランザクション(最後のOCITransCommit()、またはOCISessionBegin() 以降に実行された一連の文として定義されます)がロールバックされます。

アプリケーションがオブジェクト・モードで実行されている場合は、このトランザクションで修正または更新されたオブジェクト・キャッシュ内のオブジェクトも同様にロールバックされます。

OCITransRollback()は、アクティブなセッションレス・トランザクションをロールバックできます。現在アクティブでないグローバル・トランザクションをロールバックしようとすると、エラーになります。

ノート:

ユーザーは、ローカル・トランザクションと同様のセッションレス・トランザクションをロールバックできます。

OCITransRollback()の使用方法を説明するコード例については、OCITransCommit()の例の項を参照してください。

27.7.5 OCITransForget()

完了したグローバル・トランザクションをサーバーに放棄させます。

用途

完了したグローバル・トランザクションをサーバーに放棄させます。

構文

sword OCITransForget ( OCISvcCtx     *svchp, 
                       OCIError      *errhp,
                       ub4            flags );

パラメータ

svchp (IN)

トランザクションが常駐するサービス・コンテキスト・ハンドルです。

errhp (IN)

エラー発生時の診断情報のためにOCIErrorGet()に渡すエラー・ハンドルです。

flags (IN)

このパラメータ用にOCI_DEFAULTを渡す必要があります。

コメント

完了したグローバル・トランザクションを放棄します。サーバーにより、システムのペンディング・トランザクション表からトランザクションの状態が削除されます。

放棄されるトランザクションのXIDをトランザクション・ハンドルの属性として設定します(OCI_ATTR_XID)。

27.7.6 OCITransMultiPrepare()

単一セルに複数のブランチがあるトランザクションを準備します。

用途

単一セルに複数のブランチがあるトランザクションを準備します。

構文

sword OCITransMultiPrepare ( OCISvcCtx    *svchp, 
                             ub4           numBranches, 
                             OCITrans    **txns, 
                             OCIError    **errhp);

パラメータ

srvchp (IN)

サービス・コンテキスト・ハンドルです。

numBranches (IN)

ブランチの数を指定します。この値は、次の2つのパラメータの配列サイズでもあります。

txns (IN)

準備するブランチのトランザクション・ハンドルの配列です。これらにはすべてOCI_ATTR_XIDが設定されます。グローバル・トランザクションIDは同じにしてください。

errhp (IN)

エラー・ハンドルの配列です。OCI_SUCCESSが戻されない場合、このパラメータによってどのブランチがどのエラーを受信したか示されます。

コメント

指定のグローバル・トランザクションをコミットできるように準備します。このコールは、分散トランザクションに対してのみ有効です。このコールは、コール元がトランザクションですべてのブランチを準備する場合にかぎり使用する拡張パフォーマンス機能です。

関連トピック

27.7.7 OCITransPrepare()

グローバル・トランザクションをコミットのために準備します。

用途

グローバル・トランザクションをコミットのために準備します。

構文

sword OCITransPrepare ( OCISvcCtx    *svchp, 
                        OCIError     *errhp,
                        ub4           flags );

パラメータ

svchp (IN)

サービス・コンテキスト・ハンドルです。

errhp (IN)

エラー発生時の診断情報のためにOCIErrorGet()に渡すエラー・ハンドルです。

flags (IN)

このパラメータ用にOCI_DEFAULTを渡す必要があります。

コメント

指定のグローバル・トランザクションをコミットできるように準備します。

このコールは、グローバル・トランザクションに対してのみ有効です。

このコールは、トランザクションが変更されていない場合はOCI_SUCCESS_WITH_INFOを戻します。エラー・ハンドルは、トランザクションが読取り専用であることを示します。flagsパラメータは、現在使用されていません。