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?

TSTART

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

Synopsis

TSTART:pc
TS:pc

引数

pc オプション — 後置条件式

概要

TSTART は、トランザクションの開始を表します。以下の TSTART では、それに続く TCOMMITTROLLBACK コマンドを可能にするため、データベース・オペレーションがジャーナルされます。

TSTART は、$TLEVEL 特殊変数の値をインクリメントします。$TLEVEL 値 0 は、有効なトランザクションがないことを示します。最初の TSTART はトランザクションを開始し、$TLEVEL を 1 にインクリメントします。後続の TSTART コマンドは、入れ子になったトランザクションを作成する場合があり、$TLEVEL をさらにインクリメントします。

トランザクション内で発生するすべての処理がロールバック可能なわけではありません。例えば、トランザクション内でのグローバル変数の設定はロールバックできますが、トランザクション内でのローカル変数の設定はロールバックできません。詳細は、"Caché ObjectScript の使用法" の "トランザクション処理での ObjectScript の使用法" を参照してください。

既定では、トランザクション内で発行されたロックは、そのトランザクション内で解除されたとしても、そのトランザクションが終了するまでは保持されます。この既定は、ロックの設定時にオーバーライドできます。詳細は "LOCK" コマンドを参照してください。

入れ子になったトランザクション

TSTART をトランザクション内で発行すると、入れ子になったトランザクションが開始されます。TSTART を発行すると、$TLEVEL 値がインクリメントされ、トランザクションの入れ子レベル数が示されます。入れ子になったトランザクションは、TCOMMIT を発行して入れ子のトランザクションをコミットするか、または TROLLBACK 1 を発行して入れ子のトランザクションをロールバックすることによって終了します。入れ子になったトランザクションを終了すると、$TLEVEL 値が 1 だけデクリメントされます。

  • 入れ子になったトランザクションに対して TROLLBACK 1 を発行すると、その入れ子のトランザクションに加えられた変更がロールバックされ、$TLEVEL がデクリメントされます。TROLLBACK コマンドを発行すると、発行されている TSTART のレベル数に関係なく、トランザクション全体をロールバックできます。

  • 入れ子のトランザクションに対する TCOMMIT の発行は、$TLEVEL をデクリメントしますが、入れ子のトランザクションに対する実際のコミットは延期されます。入れ子になったトランザクションの処理中に行われた変更は、最も外側のトランザクションがコミットされたとき、つまり、TCOMMIT によって $TLEVEL 値が 0 にデクリメントされたときにのみコミットされ、このコミットは取り消すことはできません。

%SYS.Journal.SystemOpens in a new tab クラスの GetImageJournalInfo()Opens in a new tab メソッドを使用して、ジャーナル・ファイル内で TSTART コマンドを検索し、開いているトランザクションを特定できます。TSTART は、$TLEVEL が 0 の場合は "BT" (Begin Transaction) ジャーナル・ファイル・レコードを、$TLEVEL が 0 よりも大きい場合は "BTL" (Begin Transaction with Level) ジャーナル・ファイル・レコードをそれぞれ書き込みます。

入れ子構造のトランザクションの最大レベル数は 255 です。この入れ子レベルの制限を超えると、<TRANSACTION LEVEL> エラーになります。

SQL とトランザクション

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

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

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

引数

pc

オプションの後置条件式。Caché は、後置条件式が True の場合に TSTART コマンドを実行し、False の場合は、TSTART コマンドは実行されません。詳細は、"Caché ObjectScript の使用法" の "コマンド後置条件式" を参照してください。

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

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}

以下の例では、TSTART を使用して、入れ子になったトランザクションを作成します。これらの例は、入れ子になったトランザクションの 3 つのロールバック・シナリオを示しています。

以下では、最も内側のトランザクションをロールバックし、中間のトランザクションをコミットし、最も外側のトランザクションをコミットします。

  KILL ^a,^b,^c
  TSTART  SET ^a=1 WRITE "tlevel=",$TLEVEL,!
    TSTART  SET ^b=2 WRITE "tlevel=",$TLEVEL,!
      TSTART  SET ^c=3 WRITE "tlevel=",$TLEVEL,!
      TROLLBACK 1 WRITE "tlevel=",$TLEVEL,!
    TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  IF $DATA(^a) {WRITE "^a=",^a,!} ELSE {WRITE "^a is undefined",!}
  IF $DATA(^b) {WRITE "^b=",^b,!} ELSE {WRITE "^b is undefined",!}
  IF $DATA(^c) {WRITE "^c=",^c,!} ELSE {WRITE "^c is undefined",!}

以下では、最も内側のトランザクションをコミットし、中間のトランザクションをロールバックし、最も外側のトランザクションをコミットします。

  KILL ^a,^b,^c
  TSTART  SET ^a=1 WRITE "tlevel=",$TLEVEL,!
    TSTART  SET ^b=2 WRITE "tlevel=",$TLEVEL,!
      TSTART  SET ^c=3 WRITE "tlevel=",$TLEVEL,!
      TCOMMIT  WRITE "tlevel=",$TLEVEL,!
    TROLLBACK 1 WRITE "tlevel=",$TLEVEL,!
  TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  IF $DATA(^a) {WRITE "^a=",^a,!} ELSE {WRITE "^a is undefined",!}
  IF $DATA(^b) {WRITE "^b=",^b,!} ELSE {WRITE "^b is undefined",!}
  IF $DATA(^c) {WRITE "^c=",^c,!} ELSE {WRITE "^c is undefined",!}

以下では、最も内側のトランザクションをコミットし、中間のトランザクションをコミットし、最も外側のトランザクションをロールバックします。

  KILL ^a,^b,^c
  TSTART  SET ^a=1  WRITE "tlevel=",$TLEVEL,!
    TSTART  SET ^b=2  WRITE "tlevel=",$TLEVEL,!
      TSTART  SET ^c=3  WRITE "tlevel=",$TLEVEL,!
      TCOMMIT  WRITE "tlevel=",$TLEVEL,!
    TCOMMIT  WRITE "tlevel=",$TLEVEL,!
  TROLLBACK 1  WRITE "tlevel=",$TLEVEL,!
  IF $DATA(^a) {WRITE "^a=",^a,!} ELSE {WRITE "^a is undefined",!}
  IF $DATA(^b) {WRITE "^b=",^b,!} ELSE {WRITE "^b is undefined",!}
  IF $DATA(^c) {WRITE "^c=",^c,!} ELSE {WRITE "^c is undefined",!}

この 3 番目のケースでは、TROLLBACK 1TROLLBACK は、どちらも $TLEVEL を 0 にデクリメントするので、同じ結果になります。

関連項目

FeedbackOpens in a new tab