『Oracle TimesTen Replication - TimesTen to TimesTen開発者および管理者ガイド』で説明されているTimesTenレプリケーション・ソリューションが要件を満たさない場合は、XLA関数を使用してデータ・ストア間で更新をレプリケートできます。
この項では、送信側のデータ・ストアをマスター、受信側のデータ・ストアをサブスクライバと呼びます。XLAを使用してデータ・ストア間の更新をレプリケートするには、まずttXlaPersistOpenまたはttXlaOpenTimesTen関数を使用してXLAハンドルを初期化します(XLAの初期化およびXLAハンドルの取得に関する項および「非永続モードでのXLAの初期化」を参照)。
XLAハンドルを両方のデータ・ストアに対して初期化した後で、次の手順を実行します。
データ・ストア間で更新レコードを送信する場合は、ttXlaTableCheck関数を使用して、マスター・データ・ストアとサブスクライバ・データ・ストアの表に互換性があることを確認します。
ttXlaTableByName、ttXlaGetTableInfoおよび ttXlaGetColumnInfo関数を使用して、レプリケートする各表のttXlaTblDesc_tおよび ttXlaColDesc_t記述を返します(これらの処理については、「更新を監視する表の指定」および「列記述の取得」を参照)。これらの記述は、ttXlaTableCheck関数に渡すことができます。出力パラメータcompatは、表に互換性があるかどうか(値が1の場合は互換性があり、値が0(ゼロ)の場合は互換性がない)を示します。この結果に基づいて、必要な処理を実行します。
次に例を示します。
SQLINTEGER compat; ttXlaTblDesc_t table; ttXlaColDesc_t columns[20]; rc = ttXlaTableCheck(xla_handle, &table, columns, &compat); if (compat) { /* Go ahead and start replicating */ } else { /* Not compatible or some other error occurred */ }
レプリケートを開始する準備の完了後、ttXlaNextUpdateまたはttXlaNextUpdateWait関数を使用してマスター・データ・ストアから更新レコードを取得し、ttXlaApply関数を使用してサブスクライバ・データ・ストアにレコードを書き込みます。
次に例を示します。
int j; SQLSMALLINT cbConnStrOut; int records; ttXlaUpdateDesc_t ** arry; do { /* get up to 15 updates */ rc = ttXlaNextUpdate(xla_handle,&arry,15,&records); if (rc != SQL_SUCCESS) { /* See "Handling XLA errors" on page 67 */ } /* print number of updates returned */ printf("Records returned by ttXlaNextUpdate : %d\n",records); /* apply the received updates */ for (j=0; j < records; j++) { ttXlaUpdateDesc_t *p; p = arry[j]; rc = ttXlaApply(xla_handle, p, 0); if (rc != SQL_SUCCESS){ /* See "Handling XLA errors" on page 67 and */ /* "Handling timeout and deadlock errors" on page 79 */ } } /* print number of updates applied */ printf("Records applied successfully : %d\n",records); } while (records != 0);
ttXlaApplyからのリターン・コードは、更新が正常に行われたかどうかを示します。リターン・コードが!= SQL_SUCCESSの場合は、更新で一時的な問題(デッドロックまたはタイムアウト)あるいは永続的な問題が発生した可能性があります。この場合、ttXlaErrorを使用すると、tt_ErrDeadlockVictim、tt_ErrTimeoutVictimなどのエラーを確認できます。一時的なエラーは、レプリケートしたトランザクションをロールバックし、再実行することでリカバリできます。その他のエラーは、重複キー違反、キーが見つからないなどの永続的エラーである可能性があります。このようなエラーは、トランザクションを再実行しても、繰り返し発生する可能性があります。
ttXlaApplyが、トランザクションのコミット・レコード(ttXlaUpdateDesc_t→flags = TT_UPDCOMMIT)をサブスクライバ・データ・ストアに適用する前にタイムアウトまたはデッドロックのエラーを返した場合は、ttXlaRollback関数を使用してトランザクションをロールバックするか、またはttXlaCommit関数を使用してサブスクライバ・データ・ストアにすでに適用済のレコードの変更をコミットします。
一時的なエラーからのリカバリを有効にするには、マスター・データ・ストアのトランザクション境界を追跡し、サブスクライバに現在適用中のトランザクションに関連付けられているレコードをユーザー・バッファに保存します。これによって、必要に応じてそれらのレコードを再適用できます。トランザクション境界は、レコード・データ・ストリーム内のコミット・レコード(ttXlaUpdateDesc_t→type = COMMITONLY)を検索することによって検出できます。トランザクションをロールバックする必要があるエラーが発生した場合は、ttXlaRollbackをコールして、サブスクライバ・データ・ストアにすでに適用済のレコードをロールバックした後、ttXlaApplyをコールして、バッファに保存されているすべてのロールバック・レコードを再適用します。
アプリケーションで、マスター・データ・ストアおよびサブスクライバ・データ・ストアの両方に対して同時に更新を行うと、更新競合が発生する場合があります。更新競合の詳細は、『Oracle TimesTen Replication - TimesTen to TimesTen開発者および管理者ガイド』の競合解消と障害回復に関する章を参照してください。
XLAで更新競合を確認するには、ttXlaApplyテスト・パラメータを設定して、UPDATETUP型の各レコードのold row値(ttXlaUpdateDesc_t→tuple1)を、サブスクライバ・データ・ストアの既存の行と比較します。更新記述のold row値がサブスクライバ・データ・ストアの対応する行と一致しない場合は、更新競合が想定されます。この場合、ttXlaApplyはサブスクライバへの更新を適用せず、sb_ErrXlaTupleMismatchエラーを返します。
TimesTen以外のデータ・ストアへの変更をレプリケートする場合は、ttXlaGenerateSQL関数を使用して、レコード・データをTimesTen以外のサブスクライバで読取りが可能なSQL文に変換します。更新レコードおよび削除レコードの場合は、正しいSQLを生成するために、NULL値可能ではない列に対する主キーまたは一意の索引がttXlaGenerateSQLに必要です。
ttXlaGenerateSQLは、パラメータとしてttXlaUpdateDesc_tを受け入れ、それと同等のSQL文をバッファに出力します。
たとえば、レコード(record)を変換し、その結果のSQL出力を200文字のバッファ(buffer)に保存するには、次の例のように入力します。
ttXlaUpdateDesc_t record; char buffer[200]; SQLINTEGER actualLength; rc = ttXlaGenerateSQL(xla_handle, &record, buffer, 200, &actualLength); if (rc != SQL_SUCCESS) { handleXLAerror (rc, xla_handle, err_buf, &native_error); if ( native_error == 8034 ) { // tt_ErrXlaNoSQL printf("Unable to translate to SQL\n"); } }バッファの実際のサイズはactualLengthパラメータによって返されます。