欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

第二十八章 Caché 命令大全 TSTART 命令

程序员文章站 2022-04-20 23:01:04
文章目录 第二十八章 Caché 命令大全 TSTART 命令重点大纲参数描述嵌套事务SQL Transactions参数pc示例 第二十八章 Caché 命令大全 TSTART 命令重点为嵌套事务发出TROLLBACK 1将回滚在该嵌套事务中所做的更改,并递减$TLEVEL。无论发出了多少级别的TSTART,都可以发出TROLLBACK来回滚整个事务。发出TSTART会递增$TLEVEL值嵌套事务期间所做的更改仅在提交最外面的事务时才不可逆转地提交;也就是说,当TCOMMIT将$TLEVEL值...

文章目录

第二十八章 Caché 命令大全 TSTART 命令

重点

  1. 为嵌套事务发出TROLLBACK 1将回滚在该嵌套事务中所做的更改,并递减$TLEVEL。无论发出了多少级别的TSTART,都可以发出TROLLBACK来回滚整个事务。
  2. 发出TSTART会递增$TLEVEL
  3. 嵌套事务期间所做的更改仅在提交最外面的事务时才不可逆转地提交;也就是说,当TCOMMIT$TLEVEL值递减为0时。
  4. 嵌套事务的最大层数为255。

大纲

TSTART:pc
TS:pc

参数

  • pc 可选 - 后置表达式

描述

TSTART标记事务的开始。在TSTART之后,记录数据库操作以启用后续的TCOMMITTROLLBACK命令。

TSTART递增$TLEVEL特殊变量的值。$TLEVEL值为0表示没有有效的事务。第一个TSTART开始一个事务,并将$TLEVEL递增到1。后续TSTART命令可以创建嵌套事务,从而进一步递增$TLEVEL

并非事务内发生的所有操作都可以回滚。例如,在事务内设置全局变量可以回滚;在事务内设置局部变量不能回滚。

默认情况下,事务内发布的锁将一直保持到事务结束,即使该锁在事务内释放也是如此。设置锁定时可以覆盖此默认值。

嵌套事务

如果在事务内发出TSTART,它将开始嵌套事务。发出TSTART会递增$TLEVEL值,指示事务嵌套的层数。可以通过发出TCOMMIT提交嵌套事务或发出TRolback1回滚嵌套事务来结束嵌套事务。结束嵌套事务会使$TLEVEL值递减1。

  • 为嵌套事务发出TROLLBACK 1将回滚在该嵌套事务中所做的更改,并递减$TLEVEL。无论发出了多少级别的TSTART,都可以发出TROLLBACK来回滚整个事务。
  • 为嵌套事务发出TCOMMIT会使$TLEVEL递减,但嵌套事务的实际提交会延迟。嵌套事务期间所做的更改仅在提交最外面的事务时才不可逆转地提交;也就是说,当TCOMMIT$TLEVEL值递减为0时。

可以使用%SYS.Journal.System类的GetImageJournalInfo()方法在日志文件中搜索TSTART命令,从而识别打开的事务。如果$TLEVEL为零,则TSTART写入“BT”(BEGIN TRANSACTION)日志文件记录,如果$TLEVEL大于0,则写入“BTL”(BEGIN TRANSACTION WITH LEVEL)日志文件记录。

嵌套事务的最大层数为255。尝试超过此嵌套级别限制会导致<Transaction Level>错误。

SQL Transactions

CachéObjectScript和SQL TRANSACTION命令完全兼容且可互换,但有以下例外:如果没有当前事务,ObjectScript TSTARTSQL START TRANSACTION都会启动事务。但是,START TRANSACTION不支持嵌套事务。因此,如果需要(或可能需要)嵌套事务,最好使用TSTART启动事务。如果需要与SQL标准兼容,请使用START TRANSACTION

CachéObjectScript事务处理为嵌套事务提供有限的支持。SQL事务处理为事务内的保存点提供支持。

参数

pc

可选的后置条件表达式。如果后置条件表达式为TRUE,则Caché执行TSTART命令;如果后置条件表达式为FALSE,则Caché不执行TSTART命令。

示例

下面的示例使用单级事务将随机金额的资金从一个帐户转移到另一个帐户。如果转帐金额大于可用余额,程序将回退事务处理:

/// d ##class(PHA.TEST.Command).TestBankAccounts()
ClassMethod TestBankAccounts()
{
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 "转移之前:",!,"Checking=$",^CHECKING(num,"balance")," Savings=$",^SAVINGS(num,"balance"),!
	// 将资金从一个账户转到另一个账户
	SET transfer=$RANDOM(1000)
	WRITE "转账金额 $",transfer,!
	DO CkToSav(num,transfer)
	IF ok=1 {
		WRITE "成功转移",!,"迄今为止的转账次数=",^NumberOfTransfers,!
	} ELSE {
		WRITE "*** 资金不足 ***",!
	}
	WRITE "转移之后:",!,"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
	}
}
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $669
*** 资金不足 ***
转移之后:
Checking=$500.99 Savings=$100.22
 
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $84
成功转移
迄今为止的转账次数=5
转移之后:
Checking=$416.99 Savings=$184.22

以下示例使用TSTART创建嵌套事务。它们显示了三种回滚嵌套事务的方案:

回滚最里面的事务,提交中间事务,提交最外面的事务:

/// d ##class(PHA.TEST.Command).TestTstart()
ClassMethod TestTstart()
{
	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",!}
}

DHC-APP>d ##class(PHA.TEST.Command).TestTstart()
tlevel=1
tlevel=2
tlevel=3
tlevel=2
tlevel=1
tlevel=0
^a=1
^b=2
^c is undefined

提交最里面的事务,回滚中间的事务,提交最外面的事务:

/// d ##class(PHA.TEST.Command).TestTstart1()
ClassMethod TestTstart1()
{
	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",!}
}

DHC-APP>d ##class(PHA.TEST.Command).TestTstart1()
tlevel=1
tlevel=2
tlevel=3
tlevel=2
tlevel=1
tlevel=0
^a=1
^b is undefined
^c is undefined

提交最里面的事务,提交中间的事务,回滚最外面的事务:

/// d ##class(PHA.TEST.Command).TestTstart2()
ClassMethod TestTstart2()
{
	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",!}
}
DHC-APP>d ##class(PHA.TEST.Command).TestTstart2()
tlevel=1
tlevel=2
tlevel=3
tlevel=2
tlevel=1
tlevel=0
^a is undefined
^b is undefined
^c is undefined

请注意,在第三种情况下,TROLLBACK 1TROLLBACK将具有相同的结果,因为两者都会将$ TLEVEL减为0。

本文地址:https://blog.csdn.net/yaoxin521123/article/details/107627702