我们有一项定期工作:
删除实体可以通过多个 SQL 命令来实现。为了确保如果操作成功,实体会被可靠地删除,我们将每个实体的处理包装在数据库事务中:
open transaction
execute DB commands to delete the entity
execute the external operation
commit the transaction
请注意,我们在运行操作之前删除了实体。否则,如果操作成功但由于某种原因随后的数据库更新失败,我们将再次处理该实体,这是不希望的。 如果外部操作失败,则会引发异常,从而阻止事务提交(有效地回滚事务并撤消“将实体标记为已处理”)。
问题是外部操作有时会运行很长时间,而我们希望加快所有实体的处理速度。 我尝试并行处理实体,但偶然发现了一个问题: 显然,当删除一个实体时,数据库锁会被放置到整个表或大范围的行上(我还没有研究过这一点)。这会导致并行运行的数据库删除失败并超时,因为它们被阻止等待长时间运行的操作周围的事务提交。
是否可以在外部操作成功时保留实体的原子删除并加快所有实体的处理速度?
数据库是 MSSQL 服务器。我的一个想法是更改实体标记为已处理的方式:不是删除它,而是添加指示成功处理的特定数据库记录。希望这不会放置如此宽的锁,也不会阻止其他线程添加此类记录。有没有其他/更好的方法?
但是可能还有另一种方法可以做你想做的事。考虑一下这个。
首先。使用输出子句执行删除。将删除的条目放入暂存表中。
第二。然后,执行外部操作。
第三。执行外部操作后,从暂存表中删除已删除的条目。
顺便说一句,由于您的整体逻辑没有描述“回滚”场景,除非您之前没有描述过“回滚”场景,所以“begin tran”无论如何都是新的,对您没有任何帮助。