【问题标题】:How to prevent race conditions in a web application如何防止 Web 应用程序中的竞争条件
【发布时间】:2015-12-16 11:02:18
【问题描述】:

我有一个网络应用程序,用户通过单击“加入”按钮进行注册。网站上可以有这么多用户,这就是为什么为了保持我的数据库查询速度快;我选择不在数据库中添加foriegnkey约束(虽然它是关系数据库)。

现在,当具有相同 userId 的用户在两个不同的浏览器中打开应用程序并同时点击“加入”按钮时会发生什么情况;将同一用户的两行添加到数据库中,这是错误的。

我必须阻止这种情况的想法是:

  1. 在存储过程和 SQL 事务隔离级别为 SERIALIZABLE 的事务中执行检查/插入逻辑;但是使用这种方法,即使两个不同的用户同时点击“JOIN”按钮,表格也会被锁定。
  2. 在 c# 中使用 lock 关键字并在其中执行检查/插入逻辑,但我相信如果来自两个浏览器的同一个用户,他们将获得自己的锁,并且仍然能够在数据库中拥有两个条目。同样对于不同的用户,它可能会产生问题,因为其他人的代码会等待第一个释放资源。
  3. 使用 EntityFramework 开箱即用支持的乐观并发,但我不确定它是否能解决我的问题。

你能帮我解决这个问题吗?

【问题讨论】:

  • 您可以创建一个插入触发器,它首先检查 id。如果存在,则从 SQL 中抛出一个错误,该错误应该向上传播,以便您在前端处理。
  • “来自两个浏览器的同一用户,他们将获得自己的锁” - 不,除非他们共享一个 AppDomain 并且可以共享一个相同的 lock 变量 - 这不会发生。

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


【解决方案1】:

您可以通过在用户名中创建唯一索引来轻松解决您的问题。所以,只有第一个会被保存。下一个会报错,因为会破坏唯一索引。

其实应该是主键。

根据您的 cmets,您的桌子很大。所以在整个表中查找一行而不在每个插入操作上使用索引肯定比在每个插入/删除/更新操作上更新索引要糟糕得多。你应该考虑一下。

无论如何,解决如果已经存在的值不插入问题的唯一方法就是检查它。

乐观并发与此无关。乐观并发与读取数据、修改数据和保存更改有关,无需锁定表。乐观并发的作用可以在以下步骤中解释:

  1. 从数据库中读取原始行,没有任何锁或事务
  2. 应用修改了原始行
  3. 当应用程序尝试保存更改时,它会检查数据库中的行是否与在步骤 1 中读取时完全相同。如果是,则保存更改。如果不是并发异常则抛出。

如此乐观的并发对你没有帮助。

我坚持使用唯一索引,这是最安全、最简单且可能更有效的解决方案。

【讨论】:

  • 我不能将它作为主键,因为还有其他一些列作为主键。此外,它是一个非常大的表,添加索引会降低更新和删除性能,并且该表上经常发生 DML 操作。
  • 感谢 JotaBe 的解释
【解决方案2】:

我会使用实体及其乐观并发。

它会将其包装在事务中并为您处理这些问题。请记住将标识和主键都放在表上。如果用户名必须是唯一的,则在表格上添加唯一的注释。

【讨论】:

  • Optmistic Concurrency 如何帮助解决问题中的问题?
猜你喜欢
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2016-12-10
相关资源
最近更新 更多