在我使用的几个存储过程之一中......事物的结构是这样的:
[begin stored proc]
BEGIN TRY
BEGIN TRANSACTION
[dump data to # tables, lots and lots of manipulation]
[output to display layer]
[UPDATES and INSERTS]
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
[handle errors]
END CATCH
[end stored proc]
这个"模板"回滚交易和处理错误基本上由团队中的其他人传递给我,回答了老板的法令,即如果SP出现任何故障,不应该进行数据修改。现在,我试图更好地了解交易,如何实施交易,最佳实践等。这看起来像是在我阅读的许多基础知识面前飞行。
我认为它应该是这样的:
[begin stored proc]
BEGIN TRY
[dump data to # tables, lots and lots of manipulation]
[output to display layer]
BEGIN TRANSACTION
[UPDATES and INSERTS]
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
[handle errors]
END CATCH
[end stored proc]
这对于这个存储过程可以正常工作,我的问题是如果我们有一个结构如下的SP:
[begin stored proc]
BEGIN TRY
[dump data to # tables, lots and lots of manipulation]
[output to display layer]
BEGIN TRANSACTION @one
[UPDATES and INSERTS]
COMMIT TRANSACTION @one
[more manipulation based on results of tran @one]
BEGIN TRANSACTION @two
[UPDATES and INSERTS]
COMMIT TRANSACTION @two
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [@one? @two?]
[handle errors]
END CATCH
[end stored proc]
提交@one后,如果后续命令失败,则不会回滚,对吗?我承认我无法想象一个场景,即所有的DML都不会在一次交易中被放置在最后,但我再也不是那么富有想象力了。在某种情况下,在任何失败的情况下,所有DML都必须回滚,是唯一的解决方案是将它全部分组到最后,还是将整个事物包装在事务中?
(如果对这些愚蠢的问题感到抱歉,我可能会从根本上误解一些事情)
答案 0 :(得分:0)
没有交易名称这样的东西。由于MSSQL中没有嵌套事务 - 无论@@trancount
值如何,调用rollback tran
会将其减少为零。如果事务已完全提交,则无法返回(除了时间点数据库还原)。
处理交易时的最佳做法是尽可能缩短交易时间。至少在OLTP系统上(或者为什么你需要它们呢?)。我不知道你的sp逻辑会影响多少数据,但这个任务看起来与ETL非常相似,ETL通常会在没有任何交易的情况下过上幸福的生活,因为它通常是 - 本质上可以玩。
如果情况并非如此,请确保您的数据库有足够的空间让其事务日志增长,因为回滚会将相同数量的数据放入其中。哦,是的,它还需要时间和磁盘资源,并保持所有锁定,直到回滚完成。如果在主数据库中启用了任何版本控制模式,tempdb
数据库中的版本存储也是如此。
如果你还没有弄明白,我的意思是你的任务要么类似ETL而且老板对交易是错误的,要么实际上可以把这些变化分成更小,更易于管理的工作单元。因为如果事务占用空间为1 Gb或更多,那么回滚它可能需要很长时间才能让脾气暴躁的人决定杀死spid,或者重新启动服务,这样只会增加头痛的数量。