2

假设房屋有居住者,并且任何房屋的两个居住者都不能具有相同的高度。

  1. 随机选择房子
  2. 获取房屋当前居住者的列表
  3. 通过检查列表来决定保留、替换、驱逐或添加哪些
  4. 确保新列表不包含任何相同高度的居住者。
  5. 用新列表替换现有列表;根据需要删除、插入或更新。

听起来很简单,但是当您有 50 个线程都试图同时执行此操作时,它会变得复杂。我在选择(步骤 2)上使用了 UPDLOCK、ROWLOCK 来阻止对我可能想要更新的任何居住者的可能更新。但是,当没有当前居住者并添加了新居住者时,我偶尔会失败。失败始终是唯一的约束违规。这绝不应该发生(参见步骤 4),但它确实发生了。

步骤 2-5 正在使用 ReadCommitted 隔离级别在 TransactionScope 内执行。

是否有一个最佳实践模型来定义应该如何处理这样的场景?

4

2 回答 2

0

我意识到这不是 SQL 或 TransactionScope 相关的问题。我正在协调数据项的集合,并且在发生这种情况时必须对集合的访问进行信号处理。就我而言,我只需要在进行协调的代码周围添加一个 lock(List) { 。}

继续进行类比,如果您要核对一份居住者名单,最好锁上门以防止居住者在您执行此操作时进出。

于 2013-04-05T22:21:47.463 回答
0

看看SQL Server 中的事务隔离级别。听起来您的问题很可能是您进行了幻读(即,有人将数据插入到您已经选择的范围中)。

在这种情况下具有高级别的并发性,我绝对建议您在隔离级别设置为 Serializable 的单个事务中运行所有关联的查询(即,SELECT 后跟适当的 INSERT/UPDATE/DELETE) . 这样,SQL Server 将确保事务在彼此完全隔离的情况下发生。

但是,在这种情况下,鉴于其高度并发性,最好的解决方案可能是在您的代码中实现某种锁定/同步,而不是仅仅依靠 SQL Server 为您完成。(虽然,我仍然建议使用 Serializable 隔离级别。)

例如,使用某种锁管理器为每个居住者和房屋生成一个锁定对象,这样您将始终为同一个居住者(或房屋)获得相同的对象,并让每个线程使用该对象进入关键部分(或类似的 C# 的Monitor.Enter) - 请注意避免死锁。这样,您可以保证在任何给定时间只有一个线程正在检查任何特定的房屋或任何特定的居住者,但仍然允许其他线程运行。

于 2013-03-16T02:56:20.077 回答