我们可以在事务中包装对存储过程的调用并指定隔离级别。
或者我们可以把事务放在存储过程里面,在那里指定一个隔离级别。
哪个更好?
我们可以在事务中包装对存储过程的调用并指定隔离级别。
或者我们可以把事务放在存储过程里面,在那里指定一个隔离级别。
哪个更好?
您应该采用一致的方法。请注意,在存储过程中回滚事务将回滚任何嵌套事务范围,包括任何外部范围。
我建议你不要在程序之外进行交易。这样,您就可以完全控制。
存储过程内部是我认为最合适的位置。
良好事务设计的基本规则之一是尽可能缩短事务的生命周期,因此提交应该在事务逻辑完成后立即发生。在存储过程之外控制事务将导致不必要地延长事务的生命周期。
您还应该考虑在过程中定义事务也会使您的代码更加清晰。否则,如果另一个编码人员需要修改给定的存储过程,他们将不得不依赖调用者确实将过程包装在事务中的事实。在过程中包含事务明确定义了您的事务处理。
仅供参考,Oracle 不支持嵌套事务,如果您在外部级别开始事务然后调用一系列存储过程,则任何发出提交的存储过程都将提交整个事务,而不仅仅是它发起的交易。因此,当从 C# 等语言调用时,您必须管理存储过程之外的事务
只是想您可能会感兴趣,以进行比较。
在数据库 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 已经提交,并且您的数据已损坏。
根据需要将交易放在尽可能高的位置,以保留其中的所有内容。
这取决于业务逻辑,如果 SP 是原子的,它应该实现自己的事务。如果您不这样做,您将在未来冒错误代码的风险,而不是创建包装事务。所以在回答你的问题时,我认为交易应该在 SP 内部进行。
当然,没有什么可以阻止您同时进行这两种操作,原子 SP 实现它们自己的事务,并且在该范围之外,可能已经存在其他更广泛的事务。
通常,在 SP 中使用事务创建时,您可能已经在事务范围内,在执行 Commit/Rollback 时必须为此实例编写代码。
我们在 Sproc 中执行以下操作,因为如果我们只是回滚它会增加外部 Sproc 中的事务计数,这可能会向应用程序生成一个警告 - 如果它不期望/处理它可能会导致应用程序错误.
但是,此方法仅回滚“本地”事务,因此外部“调用者”必须适当地解释返回值;或者使用 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