如何在web应用程序中防止竞争条件
本文关键字:竞争 条件 应用程序 web | 更新日期: 2023-09-27 18:27:03
我有一个web应用程序,用户可以通过单击按钮"加入"进行注册。网站上可能有这么多用户,这就是为什么要让我的数据库查询快速;我选择不在数据库中添加foriegney约束(尽管它是关系数据库)。
现在发生的情况是,具有相同userId的用户在两个不同的浏览器中打开应用程序,并同时点击"加入"按钮;将同一用户的两行添加到数据库中是错误的。
我必须阻止的想法是:
- 在存储过程中以及SQL事务隔离级别为SERIALIZABLE的事务中执行检查/插入逻辑;但是使用这种方法,即使两个不同的用户同时点击"JOIN"按钮,表也会被锁定
- 在c#中使用lock关键字,并从里面执行检查/插入逻辑,但我相信,如果同一个用户来自两个浏览器,他们将获得自己的锁,并且仍然可以在数据库中有两个条目。此外,对于不同的用户,这可能会造成问题,因为其他用户的代码将等待第一个用户释放资源
- 使用EntityFramework开箱即用支持的乐观并发,但我不确定它是否能解决我的问题
你能帮我做这个吗?
您可以通过在用户名中创建唯一索引来轻松解决问题。因此,只有第一个会被保存。下一个将被报告为错误,因为它会破坏唯一索引。
事实上,它应该是主键。
根据你的评论,你的桌子很大。因此,在整个表中查找一行而不在每次插入操作中使用索引,这肯定比在每次插入/删除/更新操作中更新索引要糟糕得多。你应该考虑一下。
无论如何,解决不插入值(如果已经存在)问题的唯一方法就是检查它
乐观并发与此无关。乐观并发与读取数据、修改数据和保存更改有关,而不锁定表。乐观并发的作用可以在以下步骤中解释:
- 从数据库中读取原始行,不带任何锁或事务
- 应用程序修改原始行
- 当应用程序试图保存更改时,它会检查DB中的行是否与步骤1中读取时的行完全相同。如果是,则保存更改。如果不是,则抛出并发异常
因此,乐观的并发性对您没有帮助。
我坚持使用唯一的索引,这是最安全、最简单、可能更具性能的解决方案。
我将使用实体及其乐观并发。
它将把它封装在一个事务中,并为您处理这些问题。请记住将标识和主键都放在表上。如果用户名必须是唯一的,那么在表上添加唯一的注释。