gpt4 book ai didi

.net - SQL Server 2014内存中上一个事务中止异常

转载 作者:行者123 更新时间:2023-12-03 02:56:47 24 4
gpt4 key购买 nike

我正在从事一个目前正在生产的大型项目。我们有一个大型流程,最近更改为将内存表与 SQL 2014 结合使用,以提高性能效率。

该过程使用:

  • 51 个内存中 SQL 表。
  • 50 个存储过程,用于从大约 150 个常规 SQL 表加载数据(插入)。
  • 300 个验证(短存储过程)从这 50 个内存表中选择(并插入到保存验证错误(如果存在)的内存表中)。

我们从 ADO.Net 调用此过程,首先加载存储过程,然后验证,每个 SP 使用不同的 SQL 连接。正常使用时,一切正常,大约需要 1.5 秒。

压力测试(6 个客户端 X 100 个任务)30 分钟。几分钟后,我们开始收到此 SQL 异常(每 20 个任务有 1 个 SQL 异常):

A previous transaction that the current transaction took a dependency on has aborted, 
and the current transaction can no longer commit.

Transactions in Memory-Optimized Tables

异常情况不清楚。我们在此过程中没有使用BEGIN TRANSACTIONSQL 异常每次都发生在不同的存储过程中。

经过几天的调查,我们陷入了困境,我们不再有任何想法。请求您帮助了解什么可能导致此异常以及如何处理它。

最佳答案

没有足够的信息来真正追踪问题,但我们可以尝试解释该错误的含义以及它是如何发生的,从而尽力帮助您。

首先,您可能已经知道,当内存优化表(MOT)参与事务时,一种乐观并发控制,避免任何锁并阻止等待该锁。相反,当检测到某种并发冲突时,其中一个冲突事务注定会失败并将被回滚。

MOT 的每一行都分配有多个时间戳,用于定义事务是否可以看到该行。

对于访问 MOT 的事务,在提交之前会执行特殊的验证阶段。所以整个事务由三个阶段组成——常规、验证和提交。

在常规阶段,事务对表的写入对其他事务不可见,除了对其他删除和更新可见的删除和更新之外,如果一个事务与另一个事务写入同一行,则会发生写入冲突,并且一笔交易注定会立即失败。

现在您的问题最有趣的是验证阶段。在这里,事务验证诸如是否违反了可重复读取或序列化隔离级别之类的事情。假设事务在 REPEATABLE READ 下运行,在事务开始时读取某些行,并且在验证阶段,它看到同一行已被另一个事务更新(请记住,除非写入同一行,否则其他事务的写入不可见,但是在这里你刚刚读到)。事务在这里注定失败并将被回滚。

现在,重要的是当验证阶段开始时,该事务(我们将其命名为事务 A,处于验证阶段)所做的写入对其他事务可见。但请注意,他们尚未做出 promise 。如果另一个事务(B)读取了这样的数据(由现在处于验证阶段但尚未提交的事务写入),它就会获得对A的依赖。这意味着A应该被提交,并且只有在B之后才能提交。如果由于某种原因,交易 A 在验证阶段失败,交易 B 也将注定失败,但你的问题中有异常(exception)。

现在请记住,即使您没有显式开始事务,每个语句仍然会在事务内执行。你可能认为简单的语句不会导致这样的问题,但是像MERGE这样的语句,其内部可能会执行多个读写操作,而且它们会在事务内部执行。

错误可能发生的示例(这只是为了给您一些想法):

  1. 语句 A 对某个表执行 MERGE 语句
  2. 进入验证阶段。
  3. 语句 B 执行 MERGE 并读取 A 写入的一些数据。
  4. 我们在 SERIALIZABLE 隔离级别下运行,验证阶段的 A 注意到幻像行已被其他语句 C 插入。违反了 SERIALIZABLE 级别,A 将回滚。
  5. B 依赖于 A,并且除了您的异常(exception)情况之外也会回滚。

希望这些信息能够帮助您找到问题的根源。

您还可以将隔离级别设置为快照来跟踪问题。然后,据我了解,不会执行验证步骤,并且此错误不应再出现。

关于.net - SQL Server 2014内存中上一个事务中止异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32695043/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com