当前位置:  数据库>sqlserver

SQL Server误区30日谈 第26天 SQL Server中存在真正的“事务嵌套”

    来源: 互联网  发布时间:2014-10-09

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

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

    
 
 

您可能感兴趣的文章:

  • SQL Server 2008如何进行数据库分离和附加详细介绍
  • 微软网站下载的Ms SQL Server2000 JDBC Driver,必须用英文版的SQL server2000吗?
  • 请问,这是什么错误!java.sql.SQLException: [Microsoft][ODBC SQL Server Driver][Named Pipes]??????? SQL Server?虽然分少,但一定给,只要您是前5名回复者中最好的以为!
  • 安装sql server 2008 management提示已安装 SQL Server 2005 Express的解决方法
  • SQL Server 2008 事件探查器(SQL SERVER Profiler) 列的说明
  • (X86/X64)安装sql server 2005 过程中提示“无法启动sql server的 启动”的解决方法
  • SQL Server降权运行 SQL Server 2000以GUESTS权限运行设置方法
  • MS SQL Server2014链接到MS SQL Server 2000的解决方案及问题处理
  • SQL语句实现SQL Server 2000及Sql Server 2005日志收缩(批量)
  • sql server不存在 sql server拒绝访问第1/3页
  • SQL Server误区30日谈 第5天 AWE在64位SQL SERVER中必须开启
  • 一定得帮我看看sql server2000通过sql server2000jdbc driver的代码
  • SQL Server统计SQL语句执行时间的脚本
  • SQL Server误区30日谈 第21天 数据损坏可以通过重启SQL Server来修复
  • SQL Server误区30日谈 第3天 即时文件初始化特性可以在SQL Server中开启和关闭
  • 创建 sql server 链接服务器的sql代码
  • jsp jdbc为什麽不能把数据insert到sql server 中,也不能从sql server中提取数据?!
  • 如何处理此错误:java.sql.SQLException: [Microsoft][ODBC SQL Server Driver]没有执行可选特性
  • sql server 2005 三个常用的小sql
  • SQL Server 中查看SQL句子执行所用的时间
  • 推荐SQL Server 重新恢复自动编号列的序号的sql代码
  • sql语句中单引号嵌套问题(一定要避免直接嵌套)
  • SQL集合嵌套查询的三个例子
  • 关于SQL嵌套的误解分析
  • 请问高手:sun下如何编译informix的C++,也就是嵌套sql的c++,急呀
  • sql server中嵌套游标的例子
  • SQL嵌套查询示例解析
  • SQL中嵌套SELECT 语句用法示例
  • SQL嵌套查询实例代码
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • SQL Server误区30日谈 第23天 有关锁升级的误区
  • SQL Server误区30日谈 第28天 有关大容量事务日志恢复模式的误区
  • SQL Server误区30日谈 第17天 有关页校验和的误区
  • SQL Server误区30日谈 第29天 有关堆碎片的误区
  • SQL Server误区30日谈 第25天 有关填充因子的误区
  • SQL Server误区30日谈 第8天 有关对索引进行在线操作的误区
  • SQL Server误区30日谈 第6天 有关NULL位图的三个误区
  • SQL Server误区30日谈 第7天 一个实例多个镜像和日志传送延迟
  • SQL Server误区30日谈 第22天 资源调控器可以调控IO
  • SQL Server误区30日谈 第16天 数据的损坏和修复
  • SQL Server误区30日谈 第10天 数据库镜像在故障发生后 马上就能发现
  • SQL Server误区30日谈 第27天 使用BACKUP WITH CHECKSUM可以替代DBCC CheckDB
  • SQL Server误区30日谈 第1天 正在运行的事务在服务器故障转移后继续执行
  • SQL Server误区30日谈 第9天 数据库文件收缩不会影响性能
  • SQL Server误区30日谈 第4天 DDL触发器就是INSTEAD OF触发器
  • SQL Server误区30日谈 第18天 有关FileStream的存储,垃圾回收以及其它
  • SQL Server误区30日谈 第11天 镜像在检测到故障后瞬间就能故障转移
  • SQL Server误区30日谈 第15天 CheckPoint只会将已提交的事务写入磁盘
  • SQL Server误区30日谈 第2天 DBCC CHECKDB会导致阻塞
  • SQL Server误区30日谈 第13天 在SQL Server 2000兼容模式下不能使用DMV
  • java命名空间java.sql接口statement的类成员方法: executeupdate定义及介绍
  • SQL查询分析工具 SQL Workbench/J
  • java命名空间java.sql接口connection的类成员方法: nativesql定义及介绍
  • oracle导出sql语句的结果集和保存执行的sql语句(深入分析)
  • java命名空间java.sql接口preparedstatement的类成员方法: executeupdate定义及介绍
  • SQL客户端软件 PKLite SQL Client
  • java命名空间java.sql接口rowid的类成员方法: getbytes定义及介绍
  • SQL客户端管理工具 SQuirreL SQL Client
  • java命名空间java.sql接口ref的类成员方法: getbasetypename定义及介绍
  • sql2005 大数据量检索分页的sql代码
  • java命名空间java.sql接口databasemetadata的类成员方法: getsqlkeywords定义及介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3