第二十六章 Caché 命令大全 TROLLBACK 命令
第二十六章 Caché 命令大全 TROLLBACK 命令
回滚不成功的事务。
重点
- 默认情况下,在进行事务时,其他进程会立即看到全局变量的
SET
或KILL
。为防止在提交事务之前其他用户看到在事务中调用的全局变量的SET
或KILL
,必须通过LOCK
命令协调对全局变量的访问。
大纲
TROLLBACK:pc
TRO:pc
TROLLBACK:pc 1
TRO:pc 1
参数
- pc - 可选-后置表达式
- 1 -可选 - 整数1。回滚一级嵌套。必须指定为文字。
描述
TROLLBACK
终止当前事务,并将所有日志记录的数据库值还原为它们在事务开始时保留的值。回滚有两种形式:
TROLLBACK
回滚正在进行的所有事务(无论发出了多少级别的TSTART
),并将$TLEVEL
重置为0。TROLLBACK 1
回滚嵌套事务的当前级别(由最近的TSTART
启动的事务)并将$TLEVEL
递减1。1参数必须是文字数字1;它不能是解析为1的变量或表达式。不支持1以外的数字。
可以从$TLEVEL
特殊变量确定嵌套事务的级别。当$TLEVEL
为0时调用TRolback
没有任何效果。
可以使用%SYS.Journal.System
类的GetImageJournalInfo()
方法在日志文件中搜索TSTART
命令,从而识别打开的事务。TSTART
递增$TLEVEL
并写入日志文件记录:如果$TLEVEL
为零,则为“BT”(BEGIN TRANSACTION)
记录,如果$TLEVEL
大于0,则为“BTL”(BEGIN TRANSACTION WITH LEVEL)
记录。成功执行回滚操作后,使用%SYS.Journal.System类的Sync()
方法刷新日志缓冲区。
回滚在回滚操作期间禁用Ctrl-C中断。
什么是回滚,什么不是回滚
回滚将回滚所有记录的操作。这些包括:
TROLLBACK
将大多数更改回滚到全局变量,包括SET
和KILL
操作。全局变量是许多Caché运算的基础。回滚操作不会还原局部变量。 TROLLBACK
在事务期间回滚对全局变量中的位字符串值所做的更改。但是,回滚操作不会将全局变量位字符串返回其先前的内部字符串表示形式。
TROLLBACK
回滚插入,更新和删除对SQL数据的更改。
但是,并非对应用程序所做的所有更改都记录在日志中:
TROLLBACK
不会将更改回滚到局部变量或私有进程全局变量。TROLLBACK
不会回滚对特殊变量(例如$TEST
)的更改。TROLLBACK
不会回滚对当前名称空间所做的更改。TROLLBACK
不会回滚LOCK
命令的锁定或解锁操作。TROLLBACK
不会将$INCREMENT
(或$ZINCREMENT
)更改回滚到全局变量。TROLLBACK
不会将$SEQUENCE
更改回滚到全局变量。
Caché将全局变量的SET
或KILL
视为日记交易事件;回滚事务会逆转这些操作。 Caché不会将局部变量或进程专用全局变量的SET
或KILL
视为日记交易事件;回滚交易对这些操作没有影响。
默认情况下,在进行事务时,其他进程会立即看到全局变量的SET
或KILL
。为防止在提交事务之前其他用户看到在事务中调用的全局变量的SET``或
KILL,必须通过
LOCK`命令协调对全局变量的访问。
事务回滚日志
如果在回滚操作期间发生错误,则Caché会发出错误消息,并将错误消息记录在cconsole.log操作员控制台日志文件中。可以使用管理门户网站系统操作选项来查看cconsole.log:[主页]> [系统日志]> [查看控制台日志]。
默认情况下,操作员控制台日志文件是Caché系统管理目录(Mgr)中的cconsole.log。此默认值是可配置的。转到管理门户网站系统管理选项,依次选择配置,其他设置和高级内存([主页]> [配置]> [高级内存设置])。查看和编辑ConsoleFile的当前设置。默认情况下,此设置为空,将控制台消息路由到MGR目录中的cconsole.log。如果更改此设置,则必须重新启动Caché,此更改才能生效。
错误
如果TROLLBACK
无法成功回滚事务,则会出现错误。处理行为取决于系统范围的日记帐配置设置标志“Freeze On Error”的设置([主页]> [配置]> [Jounal设置]):
-
如果未设置Freeze On Error(缺省设置),则该进程将收到
<ROLLFAIL>
错误。该事务被关闭,并且为该事务保留的任何锁都被释放。此选项以数据完整性换取系统可用性。 -
如果设置了Freeze On Error,则进程会暂停,并且清理作业守护进程(CLNDMN)会重试回滚打开的事务。在CLNDMN重试期间,为事务保留的锁是完好无损的,因此,系统可能会挂起。此选项以系统可用性换取数据完整性。
当<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>
。如果进程在所有数据库更改完成之后发出TRolback
命令之前禁用日志记录,则在事务回滚时不会发生<ROLLFAIL>
。相反,Caché会在回滚操作期间临时启用日志记录。回滚操作完成后,Caché将再次禁用日志记录
SQL事务
CachéObjectScript和SQL TRANSACTION命令完全兼容且可互换,但有以下例外:
如果没有当前事务,ObjectScript TSTART
和SQL START TRANSACTION
都会启动事务。但是,START TRANSACTION
不支持嵌套事务。因此,如果需要(或可能需要)嵌套事务,最好使用TSTART
启动事务。如果需要与SQL标准兼容,请使用START TRANSACTION
。
CachéObjectScript事务处理为嵌套事务提供有限的支持。SQL事务处理为事务内的保存点提供支持。
清除缓存查询
如果在事务期间调用%SYSTEM.SQL
类的Purge()
方法来清除缓存的查询,则缓存的查询将被永久删除。后续的TROLLBACK
将不会还原已清除的缓存查询。
Globals 与 TROLLBACK 1
TROLLBACK 1
回滚并恢复其嵌套事务中更改的所有全局变量。但是,如果将全局变量更改为映射到不支持嵌套事务的远程系统,则这些更改将视为发生在最外层的嵌套级别。仅当回滚将$ LEVEL
重置为0时(通过调用TROLLBACK
或在$ T LEVEL = 1
时调用TROLLBACK 1
时),才会此类全局变量回滚。
Locks 与 TROLLBACK 1
TROLLBACK 1
不会将在其嵌套事务期间建立的锁恢复到其先前状态。在事务期间建立的所有锁都保留在锁表中,直到通过TROLLBACK
到级别0或TCOMMIT
结束事务为止。那时,Caché释放在嵌套事务期间创建的所有锁,并将所有先前存在的锁恢复到TSTART
之前的状态。嵌套事务的TCOMMIT
不会释放相应的锁,因此后续的TROLLBACK
可以在已提交的子事务中实现锁。
参数
pc
可选的后置条件表达式。如果后置条件表达式为true(计算为非零数值),则Caché执行命令。如果后置条件表达式为假(计算为零),则Caché不执行该命令。
示例
下面的示例使用单级事务将随机金额的资金从一个帐户转移到另一个帐户。如果转帐金额大于可用余额,程序将使用回退来回退事务处理:
/// 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
转账金额 $222
成功转移
迄今为止的转账次数=1
转移之后:
Checking=$278.99 Savings=$322.22
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $5
成功转移
迄今为止的转账次数=2
转移之后:
Checking=$495.99 Savings=$105.22
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $893
*** 资金不足 ***
转移之后:
Checking=$500.99 Savings=$100.22
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $62
成功转移
迄今为止的转账次数=3
转移之后:
Checking=$438.99 Savings=$162.22
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $221
成功转移
迄今为止的转账次数=4
转移之后:
Checking=$279.99 Savings=$321.22
DHC-APP>d ##class(PHA.TEST.Command).TestBankAccounts()
转移之前:
Checking=$500.99 Savings=$100.22
转账金额 $545
*** 资金不足 ***
转移之后:
Checking=$500.99 Savings=$100.22
以下示例显示回滚对嵌套事务的影响。每个TSTART
递增$TLEVEL
并设置全局变量。在内部嵌套事务上发出TCOMMIT
会使$TLEVEL
递减,但在嵌套事务中所做更改的提交会延迟。在这种情况下,外部事务的后续回滚将回滚所做的所有更改,包括内部“已提交”嵌套事务中的更改。
/// d ##class(PHA.TEST.Command).TestTro()
ClassMethod TestTro()
{
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
}
DHC-APP>d ##class(PHA.TEST.Command).TestTro()
level:0 [- - -] [- - -]
level:1 hello [- - -]
level:2 hello world
After TCOMMIT
level:1 hello world
After TROLLBACK
level:0 [- - -] [- - -]
/// d ##class(PHA.TEST.Command).TestTro()
ClassMethod TestTro()
{
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)
TRO
WRITE !,"After TCOMMIT"
WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
TROLLBACK
WRITE !,"After TROLLBACK"
WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestTro()
level:0 [- - -] [- - -]
level:1 hello [- - -]
level:2 hello world
After TCOMMIT
level:0 [- - -] [- - -]
After TROLLBACK
level:0 [- - -] [- - -]
/// d ##class(PHA.TEST.Command).TestTro()
ClassMethod TestTro()
{
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)
TRO 1
WRITE !,"After TCOMMIT"
WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
TROLLBACK
WRITE !,"After TROLLBACK"
WRITE !,"level:",$TLEVEL," ",^a(1)," ",^b(1)
QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestTro()
level:0 [- - -] [- - -]
level:1 hello [- - -]
level:2 hello world
After TCOMMIT
level:1 hello [- - -]
After TROLLBACK
level:0 [- - -] [- - -]
下面的示例显示Troll Back
如何回滚全局变量,而不是局部变量:
/// d ##class(PHA.TEST.Command).TestTro1()
ClassMethod TestTro1()
{
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
}
DHC-APP>d ##class(PHA.TEST.Command).TestTro1()
level:0
local:default global:default
TSTART level:1
local:first global:first
TSTART level:2
local:first second global:first second
TSTART level:3
local:first second third global:first second third
After Rollback:
TROLLBACK level:0
local:first second third global:default
下面的示例显示如何不回滚对全局的$INCREMENT
更改。
/// d ##class(PHA.TEST.Command).TestTroINCREMENT()
ClassMethod TestTroINCREMENT()
{
SET ^x=-1,^y=0,^z=""
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
}
DHC-APP>d ##class(PHA.TEST.Command).TestTroINCREMENT()
level:0
Increment:0 Add:0
level:1
Increment:1 Add:1
level:2
Increment:2 Add:2
level:3
Increment:3 Add:3
After Rollback
level:0
Increment:3 Add:0
相关文章
- DOS命令符基本操作
- Linux下使用mail命令发送邮件
- Linux 命令大全-网络资源
- BSD vi/vim 命令大全(下)[转]
- windows CMD命令大全及详细解释和语法
- 宝塔Liunx面板命令大全与各个配置路径大全
- maven基础:mvn命令常用参数整理;如:-am构建指定模块,同时构建指定模块依赖的其他模块
- mongodb 命令行基本命令使用大全
- Windows 批处理(bat)语法大全、BAT批处理基本命令总结
- 【docker】Docker快速入门总结笔记(命令大全)
- ❤️十万字Linux命令大全cp详细教程(2)❤️
- 【Mac 教程系列】Mac 实用命令大全
- git命令之git clone用法
- Linux zip/unzip命令
- L65.linux命令每日一练 -- 第十章 Linux网络管理命令 -- ifdown和route
- Win 10 深度隐藏文件夹命令
- Linux基础命令-netstat显示网络状态
- 2022年ADB 命令知多少?一文2000字详细 ADB 命令大全来啦
- LINUX命令(1)-创建文件
- Linux基础命令大全(下)
- MYSQL 命令大全
- 常用命令大全(文件搜索命令+帮助命令+用户管理命令)
- Linux目录结构和常用命令大全(文件处理命令)
- kali命令大全
- maven clean install命令报错 Failed to execute goal org.apache.maven.plugins:maven-clean-plugin
- Git的基本命令大全
- 云原生之使用Docker部署Linux命令大全搜索工具