我有一个内部使用的ASP.NET C#业务webapp。我们遇到的一个问题是原始设计没有考虑并发检查 - 所以现在多个用户访问相同的数据并覆盖其他用户的更改。所以我的问题是 - 对于webapps,人们通常会使用悲观或乐观的并发系统吗?推动使用一个优先于另一个的偏好是什么以及需要考虑哪些设计考虑因素?
我目前倾向于乐观的并发检查,因为它似乎更宽容,但我担心可能会发生多次变化的可能性相互矛盾。
谢谢!
答案 0 :(得分:3)
乐观锁定。
悲观更难实现,并会在Web环境中产生问题。什么动作会释放锁定,关闭浏览器?离开会议超时?那么如果他们确实保存了他们的更改呢?
您没有指定您正在使用的数据库。 MS SQL Server具有时间戳数据类型。它与时间无关。它通常是每次更新行时都会更改的数字。你不需要做任何事情来确保它被改变,你只需要检查它。您可以使用@KM建议的最后修改日期/时间来实现类似。但这意味着每次更新行时都必须记住更改它。如果使用datetime,则需要使用具有足够精度的数据类型,以确保在最终时不能更改值。例如,有人保存一行,然后有人读取它,然后发生另一次保存,但保留修改的日期/时间。我会使用时间戳,除非有必要跟踪记录上的最后修改日期。
要检查它,您可以像@KM建议的那样进行检查,并将其包含在update语句where子句中。或者你可以开始一个事务,检查时间戳,如果一切都做得好,然后提交事务,如果没有则返回失败代码或错误。
保持交易开放(由@le dorfier建议)类似于悲观锁定,但锁定的数据量可能超过一行。大多数RDBM默认锁定在页面级别。您还会遇到与悲观锁定相同的问题。
您在问题中提到您担心更新冲突。这就是锁定肯定会阻止的。正确实施时,乐观或悲观的意志都会严格阻止。
答案 1 :(得分:3)
我同意上面的第一个答案,我们尝试在碰撞机会相当低时使用乐观锁定。这可以使用LastModifiedDate列或递增Version列轻松实现。如果您不确定碰撞的频率,请在某处记录事件,以便您可以密切关注它们。如果您的记录始终处于“编辑”模式,则具有单独的“查看”和“编辑”模式可以帮助减少冲突(假设您在进入编辑模式时重新加载数据)。
如果冲突仍然很高,悲观锁定在Web应用程序中更难实现,但绝对可能。我们在“租赁”记录方面取得了很大成功(锁定超时)......类似于在TicketMaster上购买门票时得到的2分钟警告。当用户进入编辑模式时,我们将记录放入“锁定”表中,超时为N分钟。如果其他用户尝试使用活动锁编辑记录,则会看到一条消息。您还可以通过在页面的任何回发上更新租约,甚至使用ajax计时器来实现长表单的保持活动。也没有理由不能用上面提到的标准乐观锁来支持这个。
许多应用需要两种方法的组合。
答案 2 :(得分:1)
对于许多处理相同记录的人来说,这是一个简单的解决方案。
当您加载数据时,获取最后更改的日期,我们在表格中使用LastChgDate
当您保存(更新)数据时,将“AND LastChgDate = previousLoadedLastChgDate”添加到where子句。如果更新中的行计数= 0,则在“其他人已保存此数据”的情况下发出错误并回滚所有内容,否则将保存数据。
我通常只在头表上执行上述逻辑,而不是在详细信息表上,因为它们都在一个事务中。
答案 3 :(得分:0)
我认为您遇到了“丢失更新”问题。
为了对付这个作为经验法则,当碰撞的可能性很高(或交易是短暂的)时,我会使用悲观锁定;当碰撞的可能性很低时(或交易很长时间,或者你的业务规则包含多个事务。)
你真的需要看看什么适用于你的情况并做出判断。