Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

TROLLBACK

失敗に終わったトランザクションをロールバックします。

Synopsis

TROLLBACK:pc
TRO:pc

TROLLBACK:pc 1
TRO:pc 1

引数

pc オプション — 後置条件式
1 オプション — 整数 1。1 レベルの入れ子のロールバック。リテラルとして指定する必要があります。

説明

TROLLBACK は現在のトランザクションを終了し、ジャーナルされたすべてのデータベース値を、トランザクションの開始時に保持されていた値にリストアします。TROLLBACK には、以下の 2 つの形式があります。

  • TROLLBACK は、TSTART が発行されているレベル数に関係なく、処理中のすべてのトランザクションをロールバックし、$TLEVEL を 0 にリセットします。

  • TROLLBACK 1 は、入れ子になったトランザクションの現在のレベル (最新の TSTART によって開始されたレベル) をロールバックし、$TLEVEL を 1 つデクリメントします。この 1 という引数は、リテラル値の 1 でなければならず、1 に解決される変数や式にすることはできません。1 以外の数字はサポートされていません。

$TLEVEL 特殊変数から、入れ子になったトランザクションのレベルを決定できます。$TLEVEL が 0 に設定されるときに呼び出される TROLLBACK は、何も影響を与えません。

%SYS.Journal.SystemOpens in a new tab クラスの GetImageJournalInfo()Opens in a new tab メソッドを使用して、ジャーナル・ファイル内で TSTART コマンドを検索し、開いているトランザクションを特定できます。TSTART$TLEVEL をインクリメントし、ジャーナル・ファイル・レコードに書き込みます。その場合、$TLEVEL が 0 であれば、“BT” (Begin Transaction) レコードが、$TLEVEL が 0 よりも大きければ、“BTL” (Begin Transaction with Level) レコードが書き込まれます。%SYS.Journal.SystemOpens in a new tab クラスの Sync()Opens in a new tab メソッドを使用して、成功したロールバック処理の後のジャーナル・バッファをフラッシュします。

TROLLBACK は、ロールバック処理の間、Ctrl-C の中断を無効にします。

ロールバックの対象

TROLLBACK は、ジャーナルされたすべてのオペレーションをロールバックします。これには、以下が含まれます。

  • TROLLBACK は、大半の変更を SET および KILL 処理などのグローバル変数にロールバックします。グローバル変数は多数の Caché 処理の基盤となっています。ローカル変数は、ロールバック操作では元に戻りません。

    TROLLBACK は、トランザクション中の変更をグローバル変数のビット文字列値にロールバックします。ただし、グローバル変数のビット文字列は、ロールバック操作によって以前の内部文字列表現に戻りません。

  • TROLLBACK は、挿入、更新、および削除の変更を SQL データにロールバックします。

しかし、アプリケーションによって行われたすべての変更がジャーナルされるわけではありません。

  • TROLLBACK は、ローカル変数またはプロセス・プライベート・グローバルに対する変更をロールバックしません。

  • TROLLBACK は、$TEST などの特殊変数に対する変更をロールバックしません。

  • TROLLBACK は、現在のネームスペースに対する変更をロールバックしません。

  • TROLLBACK は、LOCK コマンドのロック・オペレーションまたはアンロック・オペレーションをロールバックしません

  • TROLLBACK は、グローバル変数に対する $INCREMENT (または $ZINCREMENT) 変更をロールバックしません。

  • TROLLBACK は、グローバル変数に対する $SEQUENCE 変更をロールバックしません。

Caché では、グローバル変数の SET または KILL は、ジャーナル化されたトランザクション・イベントとして扱われます。このようなイベントでは、トランザクションをロールバックすると、これらの処理が取り消されて元の状態に戻ります。ローカル変数またはプロセス・プライベート・グローバル変数の SET または KILL は、ジャーナル化されたトランザクション・イベントとして扱われません。このようなイベントでは、トランザクションをロールバックしても、これらの処理には何の影響もありません。既定では、トランザクションの進行中、グローバル変数の SET または KILL を他のプロセスが即座に見ることができます。トランザクションの中で呼び出したグローバル変数の SET または KILL を、トランザクションがコミットされる前に他のユーザに見られないようにするには、LOCK コマンドを使用してグローバル変数へのアクセスを調整する必要があります。

トランザクション・ロールバックのロギング

ロールバック処理中にエラーが発生した場合は、<ROLLFAIL> エラー・メッセージが発行され、cconsole.log オペレータ・コンソール・ログ・ファイルにエラー・メッセージが記録されます。管理ポータルの [システム操作] オプションを使用して、cconsole.log を表示できます (システム, システムログ, コンソールログの表示)。

既定では、オペレータ・コンソール・ログ・ファイルは、Caché システム管理ディレクトリ (Mgr) にある cconsole.log ファイルです。この既定は構成可能です。管理ポータル [システム管理] オプションに移動して、[構成] を選択してから、[追加設定] を選択し、その後 [詳細メモリ] を選択します (システム,構成,詳細メモリ設定)。[ConsoleFile] の現在の設定を表示して編集します。既定では、この設定は空白で、コンソール・メッセージは MGR ディレクトリの cconsole.log に転送されます。この設定を変更した場合は、Caché を再起動して、変更を有効にする必要があります。

<ROLLFAIL> エラー

TROLLBACK がトランザクションを正常にロールバックできない場合、<ROLLFAIL> エラーが発生します。このプロセスの動作は、システム全体のジャーナル構成設定フラグ [エラー発生時に凍結する] (システム, 構成, ジャーナリング設定) の設定に応じて以下のように異なります。

  • [エラーの発生時に凍結する] が設定されていない場合 (既定)、プロセスは <ROLLFAIL> エラーを受け取ります。トランザクションは閉じられ、そのトランザクションに対して保持されているすべてのロックが解除されます。このオプションでは、データ整合性よりシステムの可用性が優先されます。

  • [エラーの発生時に凍結する] が設定されている場合、プロセスは停止し、ジョブ削除デーモン (CLNDMN) が、開いているトランザクションのロールバックを再試行します。CLNDMN が再試行している間、トランザクションに対して保持されているロックは変更されませんが、システムは停止する場合があります。このオプションでは、システムの可用性よりデータ整合性が優先されます。

詳細は、"Caché データ整合性ガイド" の "ジャーナル入出力エラー" を参照してください。

<ROLLFAIL> が発生する場合、Caché %msg は、<ROLLFAIL> エラーそのものと、ロールバックを発生させた直前のエラーを記録します。例えば、日付を範囲外の値で更新しようとしてロールバックに失敗すると、以下の %msg が返されます。SQLCODE = -105 %msg = Unexpected error occurred: <ROLLFAIL>%0Ac+1^dpv during TROLLBACK.Previous error: SQLCODE=-105, %msg='Field 'Sample.Person.DOB' (value '5888326') failed validation'.

<ROLLFAIL> は、トランザクション内で、グローバルがリモート・データベースにアクセスした後、プログラムが明示的にそのリモート・データベースをディスマウントした場合のトランザクション・ロールバック時に発生します。

<ROLLFAIL> は、データベース変更を行う前にプロセスがジャーナリングを無効にして、トランザクション・ロールバックを起動したエラーが発生した場合のトランザクション・ロールバック時に発生します。<ROLLFAIL> は、すべてのデータベース変更が行われた後、TROLLBACK コマンドを発行する前にプロセスがジャーナリングを無効にした場合のトランザクション・ロールバック時には発生しません。その代わりに、Caché は、ロールバック処理中にジャーナリングを一時的に有効にします。ロールバック処理の完了時に、Caché はジャーナリングを再び無効にします。

SQL とトランザクション

ObjectScript と SQL のトランザクション・コマンドは完全に互換性があり、置き換え可能ですが、以下の例外があります。

ObjectScript TSTART と SQL START TRANSACTION はどちらも、トランザクションが進行中でない場合にトランザクションを開始します。ただし、START TRANSACTION では、入れ子になったトランザクションはサポートされません。そのため、入れ子になったトランザクションが必要な場合 (または必要になる可能性がある場合) には、トランザクションを TSTART で始めることをお勧めします。SQL 標準との互換性が必要な場合は、START TRANSACTION を使用してください。

ObjectScript トランザクション処理は、入れ子になったトランザクションを限定的にサポートします。SQL トランザクション処理はトランザクション内のセーブポイントをサポートします。

クエリ・キャッシュの削除

トランザクションの際に %SYSTEM.SQLOpens in a new tab クラスの Purge()Opens in a new tab メソッドを呼び出してクエリ・キャッシュを削除すると、クエリ・キャッシュは永久に削除されます。後続の TROLLBACK では、削除されたクエリ・キャッシュはリストアされません。

グローバルと TROLLBACK 1

TROLLBACK 1 は、入れ子になったトランザクション内で変更されたすべてのグローバルをロールバックしてリストアします。ただし、入れ子のトランザクションをサポートしないリモート・システムにマップされたグローバルが変更された場合、その変更は入れ子の最も外側で生じたものとして処理されます。こうしたグローバルは、TROLLBACK が呼び出されるか、または $TLEVEL が 1 のときに TROLLBACK 1 が呼び出されることで、$TLEVEL が 0 にリセットされたときにのみロールバックされます。

ロックと TROLLBACK 1

TROLLBACK 1 は、入れ子になったトランザクションの実行中に設定されたロックを以前の状態にリストアしません。トランザクションの実行中に設定されたすべてのロックは、レベル 0 へのTROLLBACK または TCOMMIT によってトランザクションが終了するまで、ロック・テーブルに残ります。その時点で、Caché は入れ子になったトランザクションの実行中に作成されたすべてのロックを解放し、既存のすべてのロックを TSTART より前の状態にリストアします。

入れ子になったトランザクションの TCOMMIT は対応するロックを解除しないため、次の TROLLBACK はコミットされたサブトランザクション内でロックを実行する場合があります。

引数

pc

オプションの後置条件式です。Caché は、後置条件式が True (0 以外の数値) の場合にこのコマンドを実行します。Caché は、後置条件式が False (0) の場合はコマンドを実行しません。詳細は、"Caché ObjectScript の使用法" の "コマンド後置条件式" を参照してください。

以下の例では、口座間でランダムな金額を送金する、単一レベルのトランザクションを使用しています。送金額が利用可能な残高を超えている場合、プログラムは TROLLBACK を使用して以下のようにトランザクションをロールバックします。

SetupBankAccounts
   SET num=12345
   SET ^CHECKING(num,"balance")=500.99
   SET ^SAVINGS(num,"balance")=100.22
   IF $DATA(^NumberOfTransfers)=0 {SET ^NumberOfTransfers=0}
BankTransfer
   WRITE "Before transfer:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
   // Transfer funds from one account to another
   SET transfer=$RANDOM(1000)
   WRITE "transfer amount $",transfer,!
   DO CkToSav(num,transfer)
   IF ok=1 {WRITE "sucessful transfer",!,"Number of transfers to date=",^NumberOfTransfers,!}
   ELSE {WRITE "*** INSUFFICIENT FUNDS ***",!}
   WRITE "After transfer:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
   RETURN
CkToSav(acct,amt)
  TSTART
  SET ^CHECKING(acct,"balance") = ^CHECKING(acct,"balance") - amt
  SET ^SAVINGS(acct,"balance") = ^SAVINGS(acct,"balance") + amt
  SET ^NumberOfTransfers=^NumberOfTransfers + 1
  IF ^CHECKING(acct,"balance") > 0 {TCOMMIT  SET ok=1 QUIT:ok}
  ELSE {TROLLBACK  SET ok=0 QUIT:ok}

以下の例では、入れ子になったトランザクションでの TROLLBACK の影響を示します。各 TSTART$TLEVEL をインクリメントし、グローバルを設定します。内側の入れ子になったトランザクションで TCOMMIT を発行すると、$TLEVEL がデクリメントされますが、入れ子になったトランザクションでの変更のコミットは延期されます。この場合、外側のトランザクションにある後続の TROLLBACK により、すべての変更がロールバックされます。このロールバックには、内側の"コミット済みの" 入れ子になったトランザクションで行われた変更も含まれます。

  SET ^a(1)="[- - -]",^b(1)="[- - -]"
  WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
  TSTART
   LOCK +^a(1)
   SET ^a(1)="hello"
   WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
     TSTART
     LOCK +^b(1)
     SET ^b(1)="world"
     WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
     TCOMMIT
  WRITE !,"After TCOMMIT"
  WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
  TROLLBACK
  WRITE !,"After TROLLBACK"
  WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
  QUIT

以下の例では、TROLLBACK によってグローバル変数がロールバックされながら、ローカル変数がロールバックされないことを示します。

  SET x="default",^y="default"
  WRITE !,"level:",$TLEVEL
  WRITE !,"local:",x," global:",^y
  TSTART
  SET x="first",^y="first"
  WRITE !,"TSTART level:",$TLEVEL
  WRITE !,"local:",x," global:",^y
    TSTART
    SET x=x_" second",^y=^y_" second"
    WRITE !,"TSTART level:",$TLEVEL
    WRITE !,"local:",x," global:",^y
     TSTART
     SET x=x_" third",^y=^y_" third"
    WRITE !,"TSTART level:",$TLEVEL
    WRITE !,"local:",x," global:",^y
  TROLLBACK
  WRITE !!,"After Rollback:"
  WRITE !,"TROLLBACK level:",$TLEVEL
  WRITE !,"local:",x," global:",^y

以下の例では、グローバルに対する $INCREMENT 変更がロールバックされないことを示します。

  SET ^x=-1,^y=0
  WRITE !,"level:",$TLEVEL
  WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
  TSTART
  SET ^y=^y+1
  WRITE !,"level:",$TLEVEL
  WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
    TSTART
    SET ^y=^y+1,^z=^z_" second"
    WRITE !,"level:",$TLEVEL
    WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
     TSTART
     SET ^y=^y+1,^z=^z_" third"
     WRITE !,"level:",$TLEVEL
     WRITE !,"Increment:",$INCREMENT(^x)," Add:",^y
  TROLLBACK
  WRITE !!,"After Rollback"
  WRITE !,"level:",$TLEVEL
  WRITE !,"Increment:",^x," Add:",^y

関連項目

FeedbackOpens in a new tab