使用内存优化表时避免更新时数据丢失

问题描述 投票:0回答:1
我公司主要软件90%的业务逻辑都在数据库(存储过程)上。在上一个版本中,引入了内存优化表来替换用于在过程之间传递数据的临时表。该软件过去依靠SNAPSHOT隔离来避免由于并发事务更新相同记录而丢失数据,但现在隔离级别已更改为READ COMMITED SNAPSHOT(为了使用MO Tables)。

因为很多软件逻辑看起来像这样:

DECLARE @IdLocationsToUpdate TABLE (Id BIGINT) INSERT INTO @IdLocationsToUpdate (Id) SELECT Id FROM Warehouse.LocationEntity WHERE ..... -- Complex conditions or other inner joins UPDATE l Warehouse.LocationEntity l INNER JOIN @IdLocationsToUpdate lu ON lu.Id = l.Id -- Plus multiple other updates and logics on that list of Ids
由于缺少快照,我们现在遇到更新问题。这是因为选择并插入表变量的记录可能已被另一个事务更新,并且现在不应执行更新语句,因为其中一些记录不再满足条件。以前,这是通过快照隔离抛出的异常来避免的,该异常不允许对同一记录进行多次更新。

你建议做什么?

希望解释足够清楚。预先感谢。

第一个想法是在所有后续更新中重写第一个选择中使用的 WHERE 条件,但这会使代码更长且混乱。因此,我希望找到一种解决方案来消除数据丢失,同时避免重复的代码,或者重新启用快照隔离的方法。

sql-server transactions memory-optimized-tables
1个回答
0
投票
对于初学者来说,显而易见的事情就是开始并提交事务。

但是您还需要添加

UPDLOCK

 提示,否则它不知道您仍然希望修改这些行。

SET XACT_ABORT ON; -- always use this for better error handling and rollback BEGIN TRAN; DECLARE @IdLocationsToUpdate TABLE (Id BIGINT PRIMARY KEY); -- ideally add a primary key INSERT INTO @IdLocationsToUpdate (Id) SELECT Id FROM Warehouse.LocationEntity WITH (UPDLOCK) WHERE ..... -- Complex conditions or other inner joins UPDATE l Warehouse.LocationEntity l INNER JOIN @IdLocationsToUpdate lu ON lu.Id = l.Id COMMIT;
    
© www.soinside.com 2019 - 2024. All rights reserved.