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

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

我担心如果两个用户开始编辑相同的记录,那么最后提交更新将是'赢家',重要信息可能会丢失。想到一些解决方案,但我不知道我是否会制造更大的头痛。

  1. Do nothing and hope that two users are never going to be editing the same record at the same time. - Might never happed but what if it does?
  2. Editing routine could store a copy of the original data as well as the updates and then compare when the user has finished editing. If they differ show user and comfirm update - Would require two copies of data to be stored.
  3. Add last updated DATETIME column and check it matches when we update, if not then show differences. - requires new column in each of the relevant tables.
  4. Create an editing table that registers when users start editing a record that will be checked and prevent other users from editing same record. - would require carful thought of program flow to prevent deadlocks and records becoming locked if a user crashes out of the program.

有没有更好的解决方案,或者我应该去其中一个吗?

0
额外 编辑
意见: 1

7 答案

数据库会为你做这个。看看“select ... for update”,这是专为这种事情设计的。它会给你一个选定行的写入锁定,然后你可以提交或回滚。

0
额外

如果您希望偶尔发生冲突,乐观并发可能是您最好的选择。

Scott Mitchell wrote a comprehensive tutorial on implementing that pattern:
Implementing Optimistic Concurrency

0
额外
感谢分享。
额外 作者 Pramod Gharu,

@马克哈里森:SQL Server不支持该语法(<�码> SELECT ... FOR UPDATE </代码>)。

SQL Server等价物是 SELECT 语句提示 UPDLOCK

有关更多信息,请参阅 SQL Server联机丛书

0
额外

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

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语句并传递 newold 字段添加到存储过程。

它还具有不锁定记录的优点 - 因为我们都知道,记录最终会在不应该被锁定的情况下保持锁定状态。

0
额外

一个经典的方法如下:

  • add a boolean field , "locked" to each table.
  • set this to false by default.
  • when a user starts editing, you do this:

    • lock the row (or the whole table if you can't lock the row)
    • check the flag on the row you want to edit
    • if the flag is true then
      • inform the user that they cannot edit that row at the moment
    • else
      • set the flag to true
    • release the lock

    • when saving the record, set the flag back to false

0
额外
这是不够好的,如果设置锁= true,如果应用程序或浏览器崩溃,那么记录永远是死锁。
额外 作者 Cheung,
这波白旗解决方案“解决并发修改很难,所以我要退出”
额外 作者 Chris Marisic,
好点,@SilverNight - 你能发布正确的解决方案吗?
额外 作者 AJ.,
对于这种情况(应用程序/浏览器崩溃),您可以将ForceUnlock方法添加到应用程序,该应用程序将强制将锁定设置为False。
额外 作者 Oleksandr,

与我一起,我有一个列lastupdate(timetamp数据类型)的最佳途径。 当选择和更新只是比较这个值 此解决方案的另一个进步是您可以使用此列来追踪数据发生变化的时间。 我认为如果你只是为了更新检查而创建一个像isLock这样的柱子并不好。

0
额外

-first create filed (update time) to store last update record -when any user select record save select time, compare between select time and update time field if( update time) > (select time) that mean another user update this record after select record

0
额外