【问题标题】:re-creating blocked environment with many threads and high concurrency重建多线程、高并发的阻塞环境
【发布时间】:2017-05-03 21:26:36
【问题描述】:

我们遇到了数百个线程尝试更新表 ID similar to this post 的问题,有时会遇到以下错误:

无法在对象 dbo.theTable 中插入重复键。复制品 键值为 (100186)。

被并行执行数百次的方法执行了几个存储过程:

using (var createTempTableCommand = new SqlCommand())
{
    createTempTableCommand.CommandText = createTempTableScript;
    createTempTableCommand.Connection = omniaConnection;
    createTempTableCommand.ExecuteNonQuery();
}

foreach (var command in listOfSqlCommands)
{
    using (var da = new SqlDataAdapter(command))
    {
        da.Fill(dtResults);
    }
}

为了重新创建这样的环境/场景,是否建议简单地记录跟踪然后简单地重放它?

我们如何重建一个高并发的环境?

【问题讨论】:

    标签: c# sql sql-server visual-studio tsql


    【解决方案1】:
    1. 只有将解决方案重写为顺序而非并行时,才能避免所有死锁/脏读。
    2. 您可以接受一些错误并创建适当的错误处理。使用重复键被阻止或错误运行可以重新开始。
    3. 您可以尝试重写您的解决方案,而无需同时使用更多线程接触相同的行。您必须更改事务隔离级别 (https://msdn.microsoft.com/en-us/library/ms709374(v=vs.85).aspx),将锁定更改为行锁定(可能是 ROWLOCK、UPDLOCK 提示的组合)。此解决方案将最大限度地减少您的错误,但无法处理所有错误。

    所以我推荐 2。在某些解决方案中,更好的方式是在不进行转换的情况下运行命令 - 您可以在不阻塞其他线程的情况下处理它并在下一步中强制执行关系。

    对于“类似的帖子” - 同样的方式。错误处理在您的应用程序中会更好。防止使用类似帖子中的游标解决方案,因为这违背了数据库的基本原理。将数据收集到集合中并使用集合。

    【讨论】:

      【解决方案2】:

      我不认为跟踪是重现高并发环境的好方法,因为跟踪的成本本身会扭曲结果,而且它并不是真正为此目的而设计的。播放不一定忠实于传入事件的时间。

      我认为你最好创建特定的负载测试来解决你遇到的问题,租用一些虚拟机并从负载测试数据库中脱颖而出。

      话虽如此,跟踪是发现实际工作负载的好方法。有时,您没有看到针对您的数据库的所有活动。当特定问题出现时,也许有一些“哦,是的”工作正在运行。恐怕有数百种可能性 - 而不是在没有更多线索的情况下可以轻易诊断出来的。

      【讨论】:

      • 太棒了!你能为这种类型的测试推荐一些特定的框架吗?也许还有一些手动测试方法>?
      猜你喜欢
      • 2014-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      • 2013-03-30
      • 1970-01-01
      相关资源
      最近更新 更多