33

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

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

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

有没有更好的解决方案,还是我应该选择其中之一?

4

8 回答 8

16

如果您预计不经常发生冲突,乐观并发可能是您最好的选择。

Scott Mitchell 写了一篇关于实现该模式的综合教程:
实现乐观并发

于 2008-08-03T21:31:40.187 回答
4

A classic approach is as follows:

  • 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

于 2008-10-01T08:53:19.470 回答
2

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

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

有关详细信息,请参阅SQL Server 联机丛书

于 2008-08-04T21:54:15.463 回答
2

-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

于 2016-07-14T11:23:05.980 回答
1

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

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

(display the customer_nm field and the user changes it)

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' );

You don't have to add a new column to your table (and keep it up to date), but you do have to create more verbose SQL statements and pass new and old fields to the stored procedure.

It also has the advantage that you are not locking the records - because we all know that records will end up staying locked when they should not be...

于 2008-08-13T22:32:37.230 回答
1

SELECT FOR UPDATE and equivalents are good providing you hold the lock for a microscopic amount of time, but for a macroscopic amount (e.g. the user has the data loaded and hasn't pressed 'save' you should use optimistic concurrency as above. (Which I always think is misnamed - it's more pessimistic than 'last writer wins', which is usually the only other alternative considered.)

于 2008-10-01T05:39:22.883 回答
0

数据库将为您执行此操作。看看“select ... for update”,它就是为这种事情而设计的。它会给你一个选定行的写锁,然后你可以提交或回滚。

于 2008-08-04T02:30:09.227 回答
0

With me, the best way i have a column lastupdate (timetamp datatype). when select and update just compare this value another advance of this solution is that you can use this column to track down the time data has change. I think it is not good if you just create a colum like isLock for check update.

于 2011-06-24T07:14:00.870 回答