我的印象是,在应用于底层数据库之前,首先将SQL服务器数据库的所有更新添加到T-Log中。如果服务器崩溃,还原过程将回滚任何未提交的事务。我还假设它适用于事务,如果未调用提交或回滚,则不会进行更改。
所以我想看看SQL服务器对交易被缩短的反应。即没有提交或回滚的事务更新。我发现我不太明白。特别是,SQL服务器如何允许这种情况发生。
我使用下面的脚本将行插入到表中并延迟,以便在到达提交或回滚之前给我足够的时间来停止事务。我想这将在交易完成之前模拟客户端应用程序超时。
Create Table MyTest (Comment varchar(20))
Go
Create Procedure MyProc
as
Begin Try
Begin Transaction
Insert Into MyTest Select 'My First Entry'
WaitFor Delay '00:00:02'
Insert Into MyTest Select 'My Second Entry'
WaitFor Delay '00:00:02'
Insert Into MyTest Select 'My Third Entry'
Commit Transaction
Return 0 -- success
End Try
Begin Catch
If (@@trancount<>0) Rollback Transaction
Declare @err int, @err_msg varchar(max)
Select @err = error_number(), @err_msg = error_message()
Raiserror(@err_msg, 16,1)
Return @err
End Catch
如果您运行脚本,根据停止过程的速度,您将看到前一个或两个插入将保留在表中。有人可以解释为什么会这样吗?
Select * From MyTest
我在SQL 2008上测试了这个。
答案 0 :(得分:2)
正确,TXN使用“Write Ahead Logging”写入。有关于它的MSDB文章以及它如何与提交/回滚/检查点等交互
但是,命令timout(或者您正在执行的操作只是停止代码执行)并且TXN永远不会回滚并且锁定将被释放,直到连接关闭(或稍后单独完成)。这就是SET XACT_ABORT的用途
答案 1 :(得分:1)
如果您开始交易并且不提交或回滚,您只需获得一个挂起的交易,该交易可能会阻止其他用户,直到当前交易完成。 SQL Server不会自动提交或回滚事务,只是因为您的代码没有这样做。该事务将保留在原位并阻止其他用户,直到它被提交或回滚为止。
现在,我可以很容易地在我的T-SQL代码中开始一个事务,而不是提交或回滚它,并执行Select语句并查看我刚刚插入或更新的数据,只要Select语句正在使用与我的交易相同的连接。如果我尝试使用其他事务进行选择,我将看不到插入或更新的数据。事实上,在完成另一个连接上的事务之前,Select语句可能根本无法完成。