SQL Server 事务 - 使用建议

3
我在不止一个地方看到这句话:"事务应尽可能保持短暂,以避免并发问题,并启用最大数量的正向提交。" 这句话真正的含义是什么呢?现在让我困惑了,因为我想在我的应用中使用事务,该应用在正常使用时将从许多客户端并发处理插入数百行的操作。例如,我有一个服务公开一个方法:AddObjects(List<Objects>),当然这些对象包含其他嵌套的不同对象。我想为每个客户端调用启动一个事务来执行适当的操作(对于每个嵌套对象执行一堆插入/更新/删除)。编辑1: 我的意思是为整个"AddObjects"调用启动一个事务,以防止未定义的状态或行为。我走错方向了吗?如果是的话,你会怎么做?有什么建议吗?编辑2: 此外,我了解到事务用于批量操作是快速的,但这与引用句子在某种程度上相矛盾。有什么结论?预先感谢您!
3个回答

3

这个建议最好理解为不要在事务中允许用户交互。如果在事务期间需要询问用户,请回滚、询问并重新运行。

除此之外,每当需要确保原子性时,请使用事务。
事务可能会导致“并发问题”,但这不是事务的问题,而是数据库可能需要更多的思考、更好的索引或更标准化的数据访问顺序。


非常感谢您的回答。您如何评价我实现“AddObjects”方法的方式?像我描述的那样可以吗?您会用另一种方式来实现它吗? - Learner

3
一项交易必须涵盖业务特定的工作单元。它与通用的“对象”无关,必须始终用特定于领域的术语来表达:“帐户X的借方和帐户Y的贷方必须在一笔交易中”,“库存项目的减法和销售必须在一笔交易中”等等。所有必须共同成功或失败的内容都必须在一个事务中。如果你沿着“将对象添加到列表是一项交易”的抽象路径走下去,那么你就走错了。所有由对象保存触发的插入/更新/删除都在一个事务中并不是目的,而是副作用。正确的语义应该是“对象X的更新和对象Y的更新必须在一个事务中”。即使是单个“对象”的退化情况也应该从特定于领域的角度来考虑。

事务可以嵌套。保存 X 和 Y 的函数可以将它们包装在一个事务中。保存 Z 的函数也可以使用事务,保存 T 也是如此。协调这三个操作的函数还可以将所有三个操作(保存 X:y、保存 Z、保存 T)都包装在一个事务中,从而有效地创建一个包含所有操作的单一事务。 - Remus Rusanu
1
有许多实用的方法可以实现这一点,比如在函数中使用TransactionScope(注意http://blogs.msdn.com/b/dbrowne/archive/2010/06/03/using-new-transactionscope-considered-harmful.aspx),和/或者使用一个事务安全的过程模板,例如http://rusanu.com/2009/06/11/exception-handling-and-nested-transactions/。 - Remus Rusanu
1
关于批量操作和事务:除了它们的正确性作用外,在某些场景(如ETL,数据上传等)中,事务不是出于正确性原因而是出于性能原因而使用:如果每个单独的语句都必须等待其自己的事务提交(和日志刷新),那么性能很快就会降低。请参见https://dev59.com/g1PTa4cB1Zd3GeqPgR1M#4598310。 - Remus Rusanu
1
“引用的那句话仍然正确,但是从不同的角度来看:并发。通过保持事务短暂,冲突和阻塞的概率降低了。在批量场景中通常没有并发,因为它们发生在“维护”时间,此时不允许进行其他活动。” - Remus Rusanu
1
总之,在正常操作中,保持事务短小,以防止并发阻塞。在批量操作中,使用较长的事务以防止等待提交日志刷新时出现阻塞。 - Remus Rusanu
显示剩余5条评论

1

为避免并发问题并实现最大数量的正向提交,事务应尽可能保持短暂。

事务开放的时间越长,就越有可能锁定其他事务所需的资源。这种阻塞会导致其他并发事务等待资源(或根据设计失败)。

Sql Server通常设置为自动提交模式。这意味着每个SQL语句都是一个独立的事务。很多时候,您需要使用多语句事务,以便可以提交或回滚多个更新。更新所需的时间越长,其他事务冲突的可能性就越大。


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