事务应该在存储过程外部指定还是内部指定?

15

我们可以将对存储过程的调用包装在一个事务中,并指定隔离级别。

或者,我们可以将事务放在存储过程内部,并在那里指定隔离级别。

哪种方法更好?

6个回答

7

您应该采用一致的方法。请注意,在存储过程中回滚事务将回滚任何嵌套事务范围,包括任何外部范围。

我建议您将事务保留在程序之外。这样,您可以保留完全控制权。


如果您嵌套多个BEGIN TRANSACTION语句,并且最深层的语句回滚,则它们全部回滚,这是不正确的。 - MatBailie
1
@Dems:你的部分说法是正确的,但只有在没有使用带有transaction_name参数的事务时才是这种情况。这就是为什么应该明确定义事务以获得完全控制。请参阅http://msdn.microsoft.com/en-us/library/ms189336.aspx了解更多信息。 - John Sansom
Dems:由于某种原因,我写成了“接受”而不是“回滚”,这没有什么意义。感谢您指出来 :-) - Tor Haugen

7

在我看来,存储过程内部是最合适的位置。

良好事务设计的基本规则之一是尽可能缩短事务生命周期,因此提交应该在事务逻辑完成后立即发生。在存储过程外控制事务将不必要地延长事务生命周期。

您还应考虑,在存储过程内定义事务也会为您的代码提供更清晰的说明。否则,如果另一个编码人员需要修改某个存储过程,则必须依赖于调用者确实将存储过程包装在事务中。在存储过程中包含事务可以明确定义您的事务处理。


4
谁决定给分数-1,提供你的理由是礼貌的。 - John Sansom

5

提醒一下,Oracle不支持嵌套事务。如果您在外部级别开始一个事务,然后调用一系列存储过程,任何发出提交命令的存储过程都会提交到目前为止的整个事务,而不仅仅是它自己所引发的事务。因此,在像C#这样的语言中调用时,您必须在存储过程之外管理事务。

只是想与您分享做个比较。


它确实支持自主事务,这使您可以在当前事务之外启动新事务。但是它们几乎总是不好的想法。它还支持保存点。这允许部分回滚,尽管我没有使用过。 - Matthew Watson

4

如果您在数据库API的外部层进行操作,那么如果您在每个存储过程中都进行提交,那么您可能会像开启自动提交一样,考虑以下存储过程:

如果您在每个存储过程中进行提交,在出现错误时,您将无法回滚整个事务,因此建议您在外部层控制事务提交。

create_user_with_email_address
  calls -> create_user
  calls -> create_email_address

如果在create_user/create_email_address中提交了任何一个,则create_user_with_email_address不再是事务性的。如果create_email_address失败,则create_user已经被提交,您将会得到破损的数据。

将事务置于所需的最高位置以使其包含所有内容。


我不认为这是正确的,如果外部事务回滚,那么任何嵌套的事务也会被回滚。 - tpower
根据您的数据库,有些数据库没有“嵌套事务”。 - Matthew Watson

2

这取决于业务逻辑,如果存储过程是原子性的,则应该实现自己的事务。如果不这样做,未来可能会出现错误代码而没有创建包装事务的风险。因此,回答你的问题,我认为事务应该放在存储过程内部。

当然,你也可以同时进行两种方式,即原子性存储过程实现自己的事务,而在此范围之外,其他更广泛的事务可能已经存在。

通常在存储过程中使用事务时,你可能已经处于事务范围内,因此在执行提交/回滚时必须对此进行编码。


1
存储过程内的事务不会加入外部事务范围,因此提交/回滚将无法透明地工作,您是否同意? - Jakob Christensen

1
我们在Sproc内部执行以下操作,因为如果我们只回滚它,会破坏外部SProcs中的事务计数,这可能会向应用程序生成警告 - 如果应用程序没有预期/处理它,可能会导致应用程序错误。
但是,此方法仅回滚“本地”事务,因此外部“调用者”必须适当地解释返回值;或者使用RAISERROR或类似方法。
BEGIN TRANSACTION MySprocName_01
SAVE  TRANSACTION MySprocName_02
...
IF @ErrorFlag = 0
BEGIN
    COMMIT TRANSACTION MySprocName_01
END
ELSE
BEGIN
    ROLLBACK TRANSACTION MySprocName_02
    COMMIT TRANSACTION MySprocName_01
END

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接