本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVERYTHING!!,经过我们团队的翻译和整理发布在AgileSharp上。希望对大家有所帮助。

误区 #26: SQL Server中存在真正的“事务嵌套”

错误

嵌套事务可不会像其语法表现的那样看起来允许事务嵌套。我真不知道为什么有人会这样写代码,我唯一能够想到的就是某个哥们对SQL Server社区嗤之以鼻然后写了这样的代码说:“玩玩你们”。

让我更详细的解释一下,SQL Server允许你在一个事务中开启嵌套另一个事务,SQL Server允许你提交这个嵌套事务,也允许你回滚这个事务。

但是,嵌套事务并不是真正的“嵌套”,对于嵌套事务来说SQL Server仅仅能够识别外层的事务。嵌套事务是日志不正常增长的罪魁祸首之一因为开发人员以为回滚了内层事务,仅仅是回滚内层事务。

但实际上当回滚内层事务时,会回滚整个内层事务,而不是仅仅是内层。这也是为什么我说嵌套事务并不存在。

所以作为开发人员来讲,永远不要对事务进行嵌套。事务嵌套是邪恶的。

如果你不相信我说的,那么通过下面的例子就就会相信。创建完数据库和表之后,每一条记录都会导致日志增加8K。

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的一个热心的家伙给的福利)

转载于:https://www.cnblogs.com/CareySon/archive/2013/01/22/2871204.html

SQL Server误区30日谈-Day26-SQL Server中存在真正的“事务嵌套”相关推荐

  1. 【译】SQL Server误区30日谈-Day1-正在运行的事务在服务器故障转移后继续执行

    本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVE ...

  2. SQL Server误区30日谈-Day21-数据损坏可以通过重启SQL Server来修复

    本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVE ...

  3. 【译】SQL Server误区30日谈-Day7-一个实例多个镜像和日志传送延迟

    本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVE ...

  4. 【译】SQL Server误区30日谈-Day2-DBCC CHECKDB会导致阻塞

    本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVE ...

  5. 【译】SQL Server误区30日谈-Day8-有关对索引进行在线操作的误区

    本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVE ...

  6. SQL Server误区30日谈-Day27-使用BACKUP ... WITH CHECKSUM可以替代DBCC CheckDB

    本系列文章是我在sqlskill.com的PAUL的博客看到的,很多误区都比较具有典型性和代表性,原文来自T-SQL Tuesday #11: Misconceptions about.... EVE ...

  7. 误区30日谈16-20

    --17 a)页校验和(Page CheckSum)在从 SQL Server 2000或升级上来之后自动开启 --答案: 错误 --解释:SQL SERVER 2005 后的数据库默认使用 CHEC ...

  8. 误区30日谈21-24

    --误区#21: 数据库损坏可以通过重启 SQL Server或是Windows, 或是附加和分离数据库解决 --答案:错误 --解释:数据库损毁无任何操作可修复,但可以通过某些机制来修复页损坏 (还 ...

  9. 浅谈实现SQL Server远距离异地容灾

    浅谈实现SQL Server远距离异地容灾 SQL Server 从2012 推出 SQL Alwayson 以来,使我们对SQL Server数据库容灾产生翻天覆地的变化. 其优点很明显 1.不依赖 ...

最新文章

  1. 陆奇新动向:将担任拼多多独立董事
  2. c++exe程序在别人电脑上双击无法打开_电脑换新系统的应用可以这样快速迁移
  3. Android构建流程——篇四
  4. 一张网页带你了解中秋节的前世今生
  5. 用Python做一个简单的翻译工具
  6. [转]spring入门(六)【springMVC中各数据源配置】
  7. 如何查看电脑是32位还是64位的
  8. android 反编译全套工具
  9. 电脑异常关机录屏/软件/程序异常停止/安卓手机/数据丢失找回方案
  10. Instant Run(App加壳)
  11. 前端灰度发布落地方案
  12. vue datepicker 动态控制时分秒 当前时间以后可选
  13. css ime-mode控制输入全角和半角
  14. 行驶证OCR识别360度全面解析
  15. gitlab迁移坑深路远
  16. PIL库中Image类thumbnail方法和resize方法区别
  17. Android 音视频配音之音频提取、截断、混音、合并、合成(二)——将提取的PCM根据时间戳截断
  18. 微软运行库合集2021
  19. 政府频频施压,58同城依旧我行我素,虚假信息顽疾无解?
  20. 服务器系统还原后如何退回去,什么是“系统还原”和“一键恢复”?

热门文章

  1. access数据库删除两个日期之间 的数据 SQL语句
  2. 现在的教育:感慨之一
  3. VMware排错:Number of virtual devices exceeds the maximum for a given controller
  4. linux之reboot
  5. 嵌入式linux webkit,嵌入式平台arm linux 之qt 4.5交叉编译到webkit时出错解决方法
  6. mysql+1.6安装,CentOS 7.0编译安装Nginx1.6.0+MySQL5.6.19+PHP5.5.14方法
  7. 手动制作自己想的语谱图
  8. Mysql报错Fatal error: Can#39;t open and lock privilege tables: Table #39;mysql.host#39; doesn#39;t...
  9. 浅谈分布式计算的开发与实现
  10. Embedding Lua, in Scala, using Java(转)