SQLServer误区30日谈第26天SQLServer中存在真正的“事务嵌套”
2023-06-13 09:14:43 时间
误区#26:SQLServer中存在真正的“事务嵌套”
错误
嵌套事务可不会像其语法表现的那样看起来允许事务嵌套。我真不知道为什么有人会这样写代码,我唯一能够想到的就是某个哥们对SQLServer社区嗤之以鼻然后写了这样的代码说:“玩玩你们”。
让我更详细的解释一下,SQLServer允许你在一个事务中开启嵌套另一个事务,SQLServer允许你提交这个嵌套事务,也允许你回滚这个事务。
但是,嵌套事务并不是真正的“嵌套”,对于嵌套事务来说SQLServer仅仅能够识别外层的事务。嵌套事务是日志不正常增长的罪魁祸首之一因为开发人员以为回滚了内层事务,仅仅是回滚内层事务。
但实际上当回滚内层事务时,会回滚整个事务,而不是仅仅是内层。这也是为什么我说嵌套事务并不存在。
所以作为开发人员来讲,永远不要对事务进行嵌套。事务嵌套是邪恶的。
如果你不相信我说的,那么通过下面的例子就就会相信。创建完数据库和表之后,每一条记录都会导致日志增加8K。
CREATEDATABASENestedXactsAreNotReal;
GO
USENestedXactsAreNotReal;
GO
ALTERDATABASENestedXactsAreNotRealSETRECOVERYSIMPLE;
GO
CREATETABLEt1(c1INTIDENTITY,c2CHAR(8000)DEFAULT"a");
CREATECLUSTEREDINDEXt1c1ONt1(c1);
GO
SETNOCOUNTON;
GO
测试#1:回滚内部事务时仅仅回滚内部事务?
BEGINTRANOuterTran;
GO
INSERTINTOt1DEFAULTValues;
GO1000
BEGINTRANInnerTran;
GO
INSERTINTOt1DEFAULTValues;
GO1000
SELECT@@TRANCOUNT,COUNT(*)FROMt1;
GO
你可以看到得出的结果是2和2000,下面我来回滚内部的事务,按照我们的猜想应该只回滚1000条吧,但事实上你会得到如下结果:
ROLLBACKTRANInnerTran;
GO
消息6401,级别16,状态1,第2行
无法回滚InnerTran。找不到该名称的事务或保存点。
好吧,由
ROLLBACKTRAN;
GO
SELECT@@TRANCOUNT,COUNT(*)FROMt1;
GO
现在我得到结果是0和0。正如
测试#2:嵌套事务中内部事务提交后会保存内部事务的修改吗?
BEGINTRANOuterTran;
GO
BEGINTRANInnerTran;
GO
INSERTINTOt1DEFAULTValues;
GO1000
COMMITTRANInnerTran;
GO
SELECTCOUNT(*)FROMt1;
GO
正如我所期待,得到的结果是1000。这说明内部事务提交是会修改到磁盘的。但是如果这时外部事务回滚的话,那么不应该回滚内部事务…
ROLLBACKTRANOuterTran;
GO
SELECTCOUNT(*)FROMt1;
GO
但运行上面查询后结果是0,这说明外部事务的回滚会影响内部事务。
测试#3:提交嵌套的事务的内部事务至少可以让我清除日志吧。
在开始这个测试之前我首先清除了日志,然后运行如下代码:
BEGINTRANOuterTran;
GO
BEGINTRANInnerTran;
GO
INSERTINTOt1DEFAULTValues;
GO1000
DBCCSQLPERF("LOGSPACE");
GO
得到结果:
下面我将事务提交后运行CheckPoint(对于简单恢复模式的数据库将会截断日志),得到的结果:
COMMITTRANInnerTran;
GO
CHECKPOINT;
GO
DBCCSQLPERF("LOGSPACE");
GO
我们发现日志的使用不减反赠,这是由于日志写入了CheckPoint记录(详情请看:
COMMITTRANOuterTran;
GO
CHECKPOINT;
GO
DBCCSQLPERF("LOGSPACE");
GO
么样,日志使用百分比大幅下降了吧。
对于嵌套事务来说---JustSayno。(这句话你可以当作来自SQLSkill.com的一个热心的家伙给的福利:-)
相关文章
- 重启后的SQLServer: 一次值得纪念的变革(sqlserver重启)
- 数据库SQL Server数据库收缩:优化数据空间(sqlserver收缩)
- SQL Server连接查询:解决方案等待你(查sqlserver连接)
- 查看SQLServer数据库服务器运行状态(查sqlserver服务)
- 基于微信和SqlServer提升企业服务水平(微信 sqlserver)
- 精通SQLServer:张亮成功之路(张亮sqlserver)
- 尚硅谷全面掌握SQLServer数据库知识(尚硅谷sqlserver)
- SQL Server 的导航猫带领你成功走上数据库之路(导航猫sqlserver)
- 探索SQLServer中关联间的联系(sqlserver间关系)
- 优化SQLServer系统性能:提升锁机制(sqlserver锁优化)
- SQL Server建立精致的货币型换算系统(sqlserver货币型)
- SQLserver如何支持负整数存储(SQLserver负整数)
- 如何使用SQLServer程序集提升效率(sqlserver程序集)
- 警惕!SQLServer盗版窃取数据的威胁(sqlserver 盗版)
- SQL Server 标签:一种高效获取数据的方式(sqlserver标签)
- 提升工作效率:利用SQLServer整合实现数据无缝链接(sqlserver整合)
- 挖掘SQLServer的“微整形”秘密(sqlserver微整形)
- 记忘认SQLServer账号密码的解决办法(sqlserver密码忘)
- SQL Server单事务处理:确保数据完整性(sqlserver单事务)
- 解决SQLServer出错的两大策略(sqlserver出错2)
- SQL Server内部链接——让数据库更好用(sqlserver内链接)
- 从SQLServer谈兼容性问题(sqlserver兼容性)
- 使用SQLServer修改日期的正确方法(sqlserver修改日期)
- 分库SQLserver实现亿级数据库分库管理(sqlserver 亿级)
- 使用SQLServer实现交叉表报表(sqlserver交叉表)
- 深入浅出:掌握SqlServer交互(sqlserver交互)
- SQLServer大家莫忽视,强大功能隐于显!(sqlserver不小于)
- SQLserver如何快速导入SQL文件(sqlserver导入sql文件)
- sqlserver通用分页存储过程