在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
误区 #26: SQL Server中存在真正的“事务嵌套” 嵌套事务可不会像其语法表现的那样看起来允许事务嵌套。我真不知道为什么有人会这样写代码,我唯一能够想到的就是某个哥们对SQL Server社区嗤之以鼻然后写了这样的代码说:“玩玩你们”。 复制代码 代码如下: CREATE DATABASE NestedXactsAreNotReal; GO USE NestedXactsAreNotReal; GO ALTER DATABASE NestedXactsAreNotReal SET RECOVERY SIMPLE; GO CREATE TABLE t1 (c1 INT IDENTITY, c2 CHAR (8000) DEFAULT 'a'); CREATE CLUSTERED INDEX t1c1 ON t1 (c1); GO SET NOCOUNT ON; GO 测试 #1:回滚内部事务时仅仅回滚内部事务? 复制代码 代码如下: BEGIN TRAN OuterTran; GO INSERT INTO t1 DEFAULT Values; GO 1000 BEGIN TRAN InnerTran; GO INSERT INTO t1 DEFAULT Values; GO 1000 SELECT @@TRANCOUNT, COUNT (*) FROM t1; GO 你可以看到得出的结果是2和2000,下面我来回滚内部的事务,按照我们的猜想应该只回滚1000条吧,但事实上你会得到如下结果: 复制代码 代码如下: ROLLBACK TRAN InnerTran; GO 复制代码 代码如下: 消息 6401,级别 16,状态 1,第 2 行 无法回滚 InnerTran。找不到该名称的事务或保存点。 好吧,由Books Online来看,我只能使用外部事务的名称或是将事务名称留空来进行回滚,代码如下: 复制代码 代码如下: ROLLBACK TRAN; GO SELECT @@TRANCOUNT, COUNT (*) FROM t1; GO 现在我得到结果是0和0。正如Books Online所言,这个回滚操作将外部事务进行了回滚并将全局变量@@TRANCOUNT设置为0。事务中所有的修改都被回滚,如果想部分回滚的话只能使用SAVE TRAN 和ROLLBACK TRAN。 测试 #2:嵌套事务中内部事务提交后会保存内部事务的修改吗? 复制代码 代码如下: BEGIN TRAN OuterTran; GO BEGIN TRAN InnerTran; GO INSERT INTO t1 DEFAULT Values; GO 1000 COMMIT TRAN InnerTran; GO SELECT COUNT (*) FROM t1; GO 正如我所期待,得到的结果是1000。这说明内部事务提交是会修改到磁盘的。但是如果这时外部事务回滚的话,那么不应该回滚内部事务… 复制代码 代码如下: ROLLBACK TRAN OuterTran; GO SELECT COUNT (*) FROM t1; GO 但运行上面查询后结果是0,这说明外部事务的回滚会影响内部事务。 测试 #3:提交嵌套的事务的内部事务至少可以让我清除日志吧。 在开始这个测试之前我首先清除了日志,然后运行如下代码: 复制代码 代码如下: BEGIN TRAN OuterTran; GO BEGIN TRAN InnerTran; GO INSERT INTO t1 DEFAULT Values; GO 1000 DBCC SQLPERF ('LOGSPACE'); GO 得到结果: 下面我将事务提交后运行CheckPoint(对于简单恢复模式的数据库将会截断日志),得到的结果: 复制代码 代码如下: COMMIT TRAN InnerTran; GO CHECKPOINT; GO DBCC SQLPERF ('LOGSPACE'); GO 我们发现日志的使用不减反赠,这是由于日志写入了CheckPoint记录(详情请看:How do checkpoints work and what gets logged)。提交内部事务不会导致日志被清除,这是由于外部事务回滚时也会连同内部事务一起回滚(译者注:所以这部分VLF在外部事务提交之前永远不会被标记位reusable)。所以这部分日志在外部事务提交之前永远不会被截断。为了证明这一点,我提交外部事务,然后再来看日志: 复制代码 代码如下: COMMIT TRAN OuterTran; GO CHECKPOINT; GO DBCC SQLPERF ('LOGSPACE'); GO 么样,日志使用百分比大幅下降了吧。 对于嵌套事务来说---Just Say no。(这句话你可以当作来自SQLSkill.com的一个热心的家伙给的福利:-) |
请发表评论