27.7 トランザクション関数
トランザクション関数をリストし、説明します。
表27-6は、この項で説明しているトランザクション関数を示しています。
表27-6 トランザクション関数
関数 | 用途 |
---|---|
サービス・コンテキスト上のトランザクションを開始します。 |
|
サービス・コンテキストからトランザクションを連結解除します。 |
|
サービス・コンテキスト上のトランザクションをコミットします。 |
|
トランザクションをロールバックします。 |
|
準備したグローバル・トランザクションを放棄します。 |
|
単一セルに複数のブランチがあるトランザクションを準備します。 |
|
グローバル・トランザクションをコミットのために準備します。 |
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_RESUME
とOCI_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_NEW
、OCI_TRANS_JOIN
、OCI_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_READONLY
、OCI_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
- トランザクション・タイプ: このカテゴリに指定できるフラグのタイプは1つのみです。フラグが指定されていない場合は、デフォルトで、密結合グローバル・トランザクション(
- APIに渡されたフラグの組合せが無効です
- 無効なXIDが使用されています
- セッションにはすでにアクティブなローカル・トランザクションがあります
- セッションにグローバル・トランザクションがあり、XIDで指定された新規トランザクションを開始するために接続解除できませんでした
- グローバル・トランザクションの開始または再開中にタイムアウトが発生しました
コメント
この関数は、グローバル・トランザクション、シリアライズ可能トランザクションまたはセッションレス・トランザクションの開始を設定します。flags
パラメータに新規トランザクションの開始が指定されている場合は、このコールの終了時点で、サービス・コンテキスト・ハンドルに現在対応付けられているトランザクション・コンテキストが初期化されます。
コールを使用してグローバル・トランザクションを制御する場合は、トランザクション識別子(XID構造体)をトランザクション・ハンドルのOCI_ATTR_XID
属性として設定する必要があります(そのポインタはサービス・コンテキスト・ハンドルsvchp
のOCI_ATTR_TRANS
属性として設定されます)。このコールを使用して新しいセッションレス・トランザクションを開始する場合は、
属性を、新しいトランザクションのグローバル・トランザクションID (GTRID)を指定するトランザクション識別子(XID構造体)に設定するか、生成されたGTRIDをリクエストするためにNULLポインタに設定できます。セッションレス・トランザクションを再開するためにコールを使用する場合。OCI_ATTR_XID
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
: 事後コール一時停止をリクエストします。一時停止は、次のサーバー・ラウンドトリップに接続され、メイン・コールの後に実行されます。
ラウンドトリップ・コールは、ゼロ以外のサーバー・ラウンドトリップを引き起こすコールです。関連項目:
OCI関数のサーバー・ラウンドトリップ
コメント
コールを使用してグローバル・トランザクションを接続解除すると、このコールの最後にトランザクションは非アクティブになります。セッションレス・トランザクションを一時停止するためにコールが使用されている場合、一時停止はただちに発生するか、次のサーバー・ラウンドトリップに接続してメイン・コールの前に実行するか(事前コール一時停止)、次のサーバー・ラウンドトリップに接続してメイン・コールの後に実行するか(事後コール・ピギーバック)のいずれかです。
このトランザクションは、後で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を開始することを示します。BATCH
とIMMEDIATE
の両方を指定するとエラーが発生します。デフォルトはIMMEDIATE
です。OCI_TRANS_WRITEWAIT
- これは、コミットのREDOバッファをオンラインREDOログに書き込むようLGWRに要求し、書き込まれるまではコミットを待機させます。WAIT
とは、トランザクションに対応するインメモリーREDOバッファが永続オンラインREDOログに書き込まれて初めてコミットが終了することを示します。OCI_TRANS_WRITENOWAIT
- これは、コミットのREDOバッファをオンラインREDOログに書き込むようLGWRに要求しますが、バッファがオンラインREDOログに書き込まれるのを待たずにコミットは終了します。NOWAIT
とは、インメモリーREDOバッファをオンラインREDOログにフラッシュせずにコミットが終了することを示します。WAIT
とNOWAIT
の両方を指定するとエラーが発生します。デフォルトは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 );
パラメータ
コメント
カレント・トランザクション(最後のOCITransCommit()
、またはOCISessionBegin()
以降に実行された一連の文として定義されます)がロールバックされます。
アプリケーションがオブジェクト・モードで実行されている場合は、このトランザクションで修正または更新されたオブジェクト・キャッシュ内のオブジェクトも同様にロールバックされます。
OCITransRollback()
は、アクティブなセッションレス・トランザクションをロールバックできます。現在アクティブでないグローバル・トランザクションをロールバックしようとすると、エラーになります。
ノート:
ユーザーは、ローカル・トランザクションと同様のセッションレス・トランザクションをロールバックできます。例
OCITransRollback()
の使用方法を説明するコード例については、OCITransCommit()の例の項を参照してください。
27.7.5 OCITransForget()
完了したグローバル・トランザクションをサーバーに放棄させます。
用途
完了したグローバル・トランザクションをサーバーに放棄させます。
構文
sword OCITransForget ( OCISvcCtx *svchp, OCIError *errhp, ub4 flags );
パラメータ
コメント
完了したグローバル・トランザクションを放棄します。サーバーにより、システムのペンディング・トランザクション表からトランザクションの状態が削除されます。
放棄されるトランザクションのXIDをトランザクション・ハンドルの属性として設定します(OCI_ATTR_XID
)。
27.7.6 OCITransMultiPrepare()
単一セルに複数のブランチがあるトランザクションを準備します。
用途
単一セルに複数のブランチがあるトランザクションを準備します。
構文
sword OCITransMultiPrepare ( OCISvcCtx *svchp, ub4 numBranches, OCITrans **txns, OCIError **errhp);
パラメータ
コメント
指定のグローバル・トランザクションをコミットできるように準備します。このコールは、分散トランザクションに対してのみ有効です。このコールは、コール元がトランザクションですべてのブランチを準備する場合にかぎり使用する拡張パフォーマンス機能です。
関連トピック
27.7.7 OCITransPrepare()
グローバル・トランザクションをコミットのために準備します。
用途
グローバル・トランザクションをコミットのために準備します。
構文
sword OCITransPrepare ( OCISvcCtx *svchp, OCIError *errhp, ub4 flags );
パラメータ
コメント
指定のグローバル・トランザクションをコミットできるように準備します。
このコールは、グローバル・トランザクションに対してのみ有効です。
このコールは、トランザクションが変更されていない場合はOCI_SUCCESS_WITH_INFO
を戻します。エラー・ハンドルは、トランザクションが読取り専用であることを示します。flags
パラメータは、現在使用されていません。