当前事务试图更新自该事务启动以来已更新的记录.事务已中止



我正在尝试更新一个表,该表是内存OLTP。在这种情况下,我们可能不得不并行地更新同一行。在同一记录的并发更新过程中,我收到了以下报告的错误。这是我的示例更新声明。

在SQL窗口1中执行以下命令,同时在窗口2中执行第二个更新命令

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRANSACTION
BEGIN TRY   
UPDATE [TestInmemory] SET CreatedDate = GETDATE() WHERE Id = 112
WAITFOR DELAY '00:00:30'
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE( )   
ROLLBACK TRANSACTION
END CATCH

窗口2:

UPDATE [TestInmemory] SET CreatedDate = GETDATE() WHERE Id = 112

现在我得到以下报告的错误。但正常表也是如此,第二个窗口正在等待完成第一个窗口事务。我该如何为内存优化表设置至少相同的行为。

System.Data.SqlClient.SqlException(0x80131904(:当前事务试图更新自该事务启动以来已更新的记录。事务已中止。语句已终止
位于System.Data.SqlClient.SqlCommand。<gt;c.b_126_0(System.Threading.ExecutionContext.RunInternal的任务1 result) at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke(((ExecutionContext ExecutionContext,ContextCallback回调,对象状态(

场景略有不同,但我看到的结果是相同的错误。就在我把表格改成MOT之后,它就开始发生了。这在我看来很糟糕。如果人们还没有这么做的话,我们应该写一篇谴责并告诉微软。

有点难过,因为他们对赫卡顿做了大量的交易,而这本应是他们解决锁定问题的答案。

我找到了答案。除非执行快照隔离,否则不支持长话短说的显式事务(BEGIN TRAN(。

解决方案1:更改数据库当前将MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT=设置为打开;

可能是最方便的。运行上面的ALTERDATABASE将告诉您的数据库在一次快照中自动对所有内存优化的内容使用快照隔离。这是一个一次性的,设置它并忘记它的选项。

解决方案2:在每个查询中的表名后面使用with(snapshot(。有点像你的做法(nolock(。

从上到下阅读这个链接,它解释了一切。

https://learn.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/transactions-with-memory-optimized-tables?view=sql-服务器-ver16

最新更新