由多个用户编辑数据库记录

时间:2008-08-03 21:23:41

标签: sql-server database

我设计了数据库表(在MS SQL服务器上规范化),并为一个应用程序创建了一个独立的Windows前端,供少数用户用来添加和编辑信息。我们将添加一个Web界面,以便日后在我们的生产区域进行搜索。

我担心如果两个用户开始编辑同一个记录,那么提交更新的最后一个将是“赢家”,重要信息可能会丢失。我想到了许多解决方案,但我不确定是否会引起更大的麻烦。

  1. 什么都不做,希望两个用户永远不会同时编辑同一条记录。 - 可能永远不会发生但是如果它发生了什么?
  2. 编辑例程可以存储原始数据的副本以及更新,然后在用户完成编辑时进行比较。如果他们不同则显示用户和确认更新 - 需要存储两份数据。
  3. 添加上次更新的DATETIME列并在更新时检查它是否匹配,如果没有则显示差异。 - 需要在每个相关表格中添加新列。
  4. 创建一个编辑表,用于在用户开始编辑将要检查的记录时注册,并阻止其他用户编辑同一记录。 - 需要仔细考虑程序流,以防止死锁,并且如果用户崩溃,该记录将被锁定。
  5. 有没有更好的解决方案,还是应该选择其中一种?

8 个答案:

答案 0 :(得分:14)

如果您预计不常发生碰撞,Optimistic Concurrency可能是您最好的选择。

Scott Mitchell撰写了一份关于实施该模式的综合教程:
Implementing Optimistic Concurrency

答案 1 :(得分:2)

经典方法如下:

  • 添加一个布尔字段,“锁定”到每个表。
  • 默认情况下将此设置为false。
  • 当用户开始编辑时,请执行以下操作:

    • 锁定行(如果无法锁定行,则锁定整个表)
    • 检查要修改的行上的标记
    • 如果标志为真则
      • 告知用户目前无法编辑该行
    • 否则
      • 将标志设置为true
    • 释放锁

    • 保存记录时,将标志设置为false

答案 2 :(得分:1)

- 首先创建归档(更新时间)以存储最后更新记录 - 当任何用户选择记录保存选择时间时, 比较选择时间和更新时间字段if(更新时间)> (选择时间)表示另一个用户在选择记录

之后更新此记录

答案 3 :(得分:1)

@Mark Harrison:SQL Server不支持该语法(SELECT ... FOR UPDATE)。

SQL Server等效项是SELECT语句提示UPDLOCK

有关详细信息,请参阅SQL Server Books Online

答案 4 :(得分:1)

另一个选择是测试您正在更改的记录中的值是否与启动时的值相同:

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(显示customer_nm字段,用户更改)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

您不必向表中添加新列(并使其保持最新),但您必须创建更详细的SQL语句并传递 new old 存储过程的字段。

它还有一个优点,就是你没有锁定记录 - 因为我们都知道记录最终会在它们不应该被锁定时保持锁定...

答案 5 :(得分:1)

SELECT FOR UPDATE和等价物是很好的,只要您保持锁定一段时间,但是对于宏观数量(例如,用户已加载数据并且没有按下'保存',您应该使用上面的乐观并发(我一直认为这是错误的 - 它比'最后作家获胜'更悲观,这通常是唯一考虑的其他选择。)

答案 6 :(得分:0)

对我来说,最好的方法是使用lastupdate列(timetamp数据类型)。 选择和更新时只需比较此值 此解决方案的另一个进步是您可以使用此列来跟踪数据更改的时间。 我认为,如果您只是创建一个像isLock这样的列用于检查更新,那就不好了。

答案 7 :(得分:0)

数据库将为您完成此操作。看看“选择...更新”,这是专门为这种事情设计的。它将为您提供所选行的写锁定,然后您可以提交或回滚。