【问题标题】:Where to put BEGIN TRAN, in the code or in the stored procedure?BEGIN TRAN 应该放在代码中还是存储过程中?
【发布时间】:2021-09-30 20:05:08
【问题描述】:

假设我有一个执行 3 次插入的存储过程。为了确保一切正常,我在存储过程中添加了begincommit tran

然后从代码端(.NET、C#),程序员也在创建一个事务。

最好的方法是什么?

  • 两个地方都有吗?
  • 仅在 C# 代码中具有此功能?
  • 仅在存储过程中具有此功能?

【问题讨论】:

  • 我在程序内部投票。添加一层应用程序端事务范围很少能很好地发挥作用。
  • 我赞同@AaronBertrand 所说的话。把数据库工作交给数据库。
  • 第三次。如果您不需要分布式事务的开销,请不要使用;交易应包括最低要求。

标签: sql-server


【解决方案1】:

最好只在存储过程中这样做,原因有很多:

  • 该过程可以更好地控制何时开始和提交事务。
  • 它还可以控制隔离级别,通常应该在事务开始之前设置。
  • 它使数据库代码接近数据库(有点主观)。
  • 如果连接被切断,服务器没有意识到,客户端打开的事务可能会在一段时间内无法提交或回滚,并可能导致锁挂起,造成巨大的阻塞链
  • 客户端启动和提交事务需要通过网络进行两次额外的往返,这在低延迟应用程序中可能会出现问题。 (出于同样的原因,应该使用SET NOCOUNT ON。)事务和相关的锁定也在那个时候被延长,导致进一步的阻塞问题。

请使用SET XACT_ABORT ON,如果出现异常,这将导致自动回滚并防止它们留下挂起的事务。


使用客户端事务可能仍然有意义,尤其是分布式事务。

在客户端代码中都有事务是愚蠢和浪费的。选择其中一个选项并坚持下去。

【讨论】:

  • 此外,交易的持续时间现在不仅通过发送开始/提交所涉及的额外往返行程,而且还延长了与交易相关的任何数据来回传输所需的时间.想象一下,您正在发送一个包含 50,000 行的 TVP,并作为结果返回和显示数据。您真的希望事务在您开始通过网络发送数据之前就开始吗?并且在您使用完所有返回的数据之后才提交?
  • 是的,同意,这就是我最后一点的部分意思,已经澄清。虽然 AFAIK 事务的开始并不重要,因为 LSN 仅在第一次修改时设置(并且 TVP 是表变量,不参与用户事务),所以主要是您需要担心的提交跨度>
  • 我可能记错了,但我参与了一些案例,我们正在排除打开事务但从未执行任何操作的空闲/睡眠连接的问题 - 这些都导致了服务器上的问题。我只是认为这是您不需要引入的另一个变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 2017-10-22
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
相关资源
最近更新 更多