c# - 并行执行 CREATE DATABASE 语句会导致错误,但不会在单独的 SQL Server 实例上发生

标签 c# sql-server entity-framework

我在我的应用程序上使用最新版本的 Entity Framework (但我不认为 EF 是这里的问题,只是说明我们使用的是什么 ORM)并拥有这种 Multi-Tenancy 架构。我正在做一些用 C# 构建的压力测试,其中它创建了 X 数量的并行运行的任务来做一些事情。在整个过程开始的某个时刻,它将为每个任务(在本例中为每个租户)创建一个新数据库,然后继续处理大部分操作。但是在某些任务中,它会在我的代码中尝试创建新数据库的那部分抛出 2 个 SQL 异常。

异常(exception)#1:

Could not obtain exclusive lock on database 'model'. Retry the operation later. CREATE DATABASE failed. Some file names listed could not be created. Check related errors.

异常#2:

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

它是这两个中的任何一个,并在我的代码的同一行中抛出(当 EF 创建数据库时)。显然在 SQL Server 中,当创建一个数据库时,它一次创建一个数据库并锁定“模型”数据库(请参阅 here),因此一些正在等待的任务会引发超时或锁定“模型”错误。

这些测试是在我们的开发SQL Server 2014 实例 (12.0.4213) 上完成的,如果我执行,比如说,100 个并行任务,某些任务肯定会抛出错误,有时甚至我执行了将近一半的任务。

但这是所有这些中最令人不安的部分,当在我本地安装在我的 PC 上的其他 SQL 服务器实例 (12.0.2000) 上进行测试时,没有此类错误抛出并且完全完成我执行的所有任务(甚至并行执行 1000 个任务!)。

到目前为止我尝试过但没有奏效的解决方案:

  • 将 EF 中对象上下文的超时更改为无限
  • 尝试在连接字符串上添加更长或无限的超时
  • 尝试在 EF 上添加重试策略并使其更长且运行更频繁
  • 目前,正在尝试安装与我们的开发服务器(使用 Windows Server 2014 R2)具有相似环境的虚拟机,并在特定版本的 SQL Server 上进行测试,以查看这些版本是否与它有任何关系(是的,我太绝望了:))

无论如何,here是一个简单的 C# 控制台应用程序,您可以下载并尝试重现该问题。此测试应用程序将执行您输入的 N 个任务,并简单地创建一个数据库并在之后立即进行清理。

最佳答案

2 个观察结果:

  1. 由于根本问题与并发有关,并且访问“资源”在关键点只允许单个访问器,而不是并发访问器,因此您可能会得到不同的结果也就不足为奇了在负载下执行高度并发的场景时在两台不同的机器上。此外,可能涉及 SQL Server 引擎差异。所有这些只是试图找出并调试并发问题的类(class)的一部分,尤其是涉及到的引擎具有非常强大的并发概念。

  2. 与其通过尝试使某事可行或充分解释某种情况来违背情势,当经验表明事情行不通时,为什么不通过设计更清晰地处理问题来改变方法呢?

    • 一个选项:通过某种并发同步机制调节访问,承认 SQL Server 需要对模型数据库进行独占锁定的现实——System.Threading.Monitor 听起来关于这里发生的事情的权利,它可以让你控制超时时发生的事情,with a timeout of your choosing .这将有助于防止可能在 SQL Server 端发生的那种锁定类型的情况,这将是对当前“超时”症状的解释(尽管压力负载可能是唯一的解释)。

      <
    • 另一种选择:看看您是否可以采用完全不需要同步的方式进行设计。达到这样一种程度,您从不请求同时创建多个数据库。创建请求的某种队列——并且该队列保证仅由一个线程提供服务——请求任务对创建的结果执行异步/等待模式。

无论哪种方式,您都会遇到这样的情况,即在压力测试下这会减慢到爬行,超压负载会导致失败。关键问题是:

  • 您的设计能否处理一些可能出现的最坏情况负载的倍数,并且仍然表现出可接受的性能?
  • 如果确实发生故障,您对故障的响应是否按照您设计的方式“控制”。

关于c# - 并行执行 CREATE DATABASE 语句会导致错误,但不会在单独的 SQL Server 实例上发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36733568/

相关文章:

c# - Entity Framework 中的参数值超出范围(首先是数据库)

c# - 带有 EF6 的 System.data.Sqlite

c# - SSMS 加载项警告

c# - 无法将 NULL 值插入到列、表中;列不允许为空...但是该列是主键并且具有自动增量属性

c# - 如何设置下拉列表DataTextField显示两个数据属性字段?

sql-server - 如何在 T-SQL 中实现 ZIP JOIN?

sql - 在 SQL Server 插入查询中使用 IF - ELSE

c# - Entity Framework - 未设置外键(0/空)但导航属性不为空

c# - BeautifulSoup 类似于 C#

c# - XML 解析检查属性是否存在