TSTART (ObjectScript)
構文
TSTART:pc
TS:pc
引数
引数 | 説明 |
---|---|
pc | オプション — 後置条件式 |
概要
TSTART は、トランザクションの開始を表します。以下の TSTART では、それに続く TCOMMIT や TROLLBACK コマンドを有効にするため、データベース・オペレーションがジャーナルされます。
TSTART は、$TLEVEL 特殊変数の値をインクリメントします。$TLEVEL 値 0 は、有効なトランザクションがないことを示します。最初の TSTART はトランザクションを開始し、$TLEVEL を 1 にインクリメントします。後続の TSTART コマンドは、入れ子になったトランザクションを作成する場合があり、$TLEVEL をさらにインクリメントします。
トランザクション内で発生するすべての処理がロールバック可能なわけではありません。例えば、トランザクション内でのグローバル変数の設定はロールバックできますが、トランザクション内でのローカル変数の設定はロールバックできません。詳細は、"トランザクション処理での ObjectScript の使用法" を参照してください。
既定では、トランザクション内で発行されたロックは、そのトランザクション内で解除されたとしても、そのトランザクションが終了するまでは保持されます。この既定は、ロックの設定時にオーバーライドできます。詳細は "LOCK" コマンドを参照してください。
引数
pc
オプションの後置条件式。InterSystems IRIS は、後置条件式が True の場合、TSTART コマンドを実行し、後置条件式が False の場合、TSTART コマンドを実行しません。詳細は、"コマンド後置条件式" を参照してください。
入れ子になったトランザクション
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 トランザクション処理はトランザクション内のセーブポイントをサポートします。
例
以下の例では、口座間でランダムな金額を送金する、単一レベルのトランザクションを使用しています。送金額が利用可能な残高を超えている場合、プログラムは以下のようにトランザクションをロールバックします。
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 1 と TROLLBACK は、どちらも $TLEVEL を 0 にデクリメントするので、同じ結果になります。