【问题标题】:Suggestions on how to deal with application throwing errors due to long running transaction关于如何处理由于长时间运行的事务而导致应用程序抛出错误的建议
【发布时间】:2017-01-16 13:48:12
【问题描述】:

所以,我遇到了一些问题。 情况是,我们让这个遗留应用程序公开了一个 Web 服务,并接收从移动应用程序发送给它的数据。

最近我们开始收到来自用户的报告,称从移动应用程序提交数据的过程需要很长时间才能提交结果。

在检查 Web 服务日志时,我们会看到很多异常,它们指向代码中的不同方法。所有这些方法的共同点是,它们是对数据库的写操作。所有方法都是应用程序打开的更大 SQL 事务的一部分。

在开始写入数据库之前处理传入结果时,应用程序会进行大量检查和查找。一切都是通过实体框架完成的,并被包装在一个事务中。

似乎这些事务锁定了数据库,并阻止处理其他传入的结果,这导致尝试从应用程序提交结果超时并不断重试,直到最终通过大门。这只是我们的理论。

事务只是将新数据写入数据库 - 它不会修改任何现有数据。将其包装在事务中的唯一原因似乎是能够在事务失败时回滚事务——而不是在它工作时避免对表进行任何其他写入操作。

主要问题是,它是一个遗留应用程序,我们目前无法接触到以前在该应用程序上工作的任何人。因此,进行重写将非常耗时且容易出错。我们正在逐步淘汰这个特定问题,所以如果我们能给自己争取一些时间,那将是理想的。

如果我们的假设是正确的,即运行两个并行写入操作应该没有问题,是否有一种简单的方法可以允许多个这些事务同时运行而无需对应用程序进行重大重写?

【问题讨论】:

  • 不要打开交易并在该交易中做所有事情。您应该只在事务中进行实际的插入/更新/删除。您可能将事务保持打开的时间过长,因此阻塞读取事务的变化很大,这会导致您的问题。
  • 嗨@GuidoG,我们已经意识到这一点。问题似乎不是,我们正在阻止其他读取操作。这是事务正在阻止任何其他写入操作(自身的其他实例)。但是,正如问题中所指出的,理论上不应该有多个同时运行的问题。能以某种方式完成吗?
  • 你怎么确定你没有阻塞读操作并且你只是阻塞了写操作?其他实例是否如您所说的那样?你是怎么确定的。此外,是否有其他应用程序在此数据库上进行读取/更新?他们也可能会阻塞。
  • @GuidoG,我很确定我们正在阻止读写操作。然而,主要是写操作是一个问题,因为它们似乎导致其他传入的移动应用程序由于死锁而超时。到目前为止,我们所做的是分析代码并得出结论,总而言之,让其中两个写入操作并行运行应该没有问题。它们只是将新数据写入数据库——它们是完全独立的。但是,正如你暗示的那样,我们并不完全确定。但是,如果可能的话,我们希望在测试中尝试一下。
  • 我会从BrentOzarULTD's SQL Server First Responder Kit 开始,看看你的数据库出了什么问题。继续Capturing Deadlock Information

标签: c# sql-server entity-framework concurrency transactionscope


【解决方案1】:

首先我建议它尝试处理正在生成的锁。开始抓取 sys.dm_tran_locks 等。

您的数据库中是否有很多 FK、索引等 - 如果应用程序可以信任,您可以考虑禁用这些。

或者它可能只是最简单的一些归档 - 你可以从活动表中删除历史数据吗?这些越小越好。

最坏的情况 - 您可以创建多个数据库(例如,每个应用程序池 1 个)并手动将数据合并到一个主数据库中。

【讨论】:

  • 感谢您的评论约翰。回答您的问题:是的,它有很多 FK。我们不信任该应用程序足以禁用这些。这些数据用于报告,遗憾的是我们已用于整个数据集,因此我们无法真正存档任何内容。这可能是一个解决方案,但如果我们走得那么远,我认为重写接收结果并处理它以进行插入的过程会更容易。如前所述,我们正在逐步淘汰该应用程序,因此我们只需要它再运行几个月即可。我希望我们能找到一个更实用的解决方案来允许并行交易
  • 永远不要禁用 FK。它是这个世界上唯一能够确保您的数据库不被损坏的东西。
【解决方案2】:

您的问题是客户端如何使用数据库。从您告诉我的内容来看,客户正在锁定表格并阻止其他事物访问它们。

通常我会建议使用类似“with (NOLOCK)”的提示(取决于您的应用是否可以处理脏读),但由于您使用的是实体框架,我建议您改为查看:Get Entity Framework 6 use NOLOCK in its underneath SELECT statements

您的数据库上的隔离级别将发挥重要作用。 Isolation Levels

我建议您检查客户端如何与数据库交互。耗时较长的操作,是select、insert、update、upsert吗?您是否对其进行了分析并查看问题所在? (解释计划等...)

表上是否有索引。查询是否使用索引?

如果问题是插入/更新(upsert)问题,实体框架会处理得非常糟糕。我建议您将代码修改为类似Upsert fast in SQL Server

实体框架在处理大型数据集时很方便,但性能不佳。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-02
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    相关资源
    最近更新 更多