由多个用户编辑数据库记录
Posted
技术标签:
【中文标题】由多个用户编辑数据库记录【英文标题】:Editing database records by multiple users 【发布时间】:2010-09-05 06:37:36 【问题描述】:我设计了数据库表(标准化,在 MS SQL 服务器上),并为一个应用程序创建了一个独立的 Windows 前端,少数用户将使用它来添加和编辑信息。我们将添加一个网络界面,以便以后在我们的生产区域中进行搜索。
我担心如果两个用户开始编辑同一记录,那么最后提交更新的用户将是“赢家”,重要信息可能会丢失。我想到了许多解决方案,但我不确定我是否会造成更大的麻烦。
-
什么都不做,希望两个用户永远不会同时编辑同一条记录。 - 可能永远不会发生,但如果发生了怎么办?
编辑例程可以存储原始数据的副本以及更新,然后在用户完成编辑时进行比较。如果它们不同,则显示用户并确认更新 - 需要存储两份数据。
添加最后更新的 DATETIME 列并在我们更新时检查它是否匹配,如果不匹配则显示差异。 - 需要在每个相关表中添加新列。
创建一个编辑表,当用户开始编辑一条将被检查的记录时进行注册,并防止其他用户编辑同一条记录。 - 需要仔细考虑程序流程,以防止在用户退出程序时出现死锁和记录被锁定。
有没有更好的解决方案,或者我应该选择其中之一吗?
【问题讨论】:
【参考方案1】:如果您希望很少发生冲突,Optimistic Concurrency 可能是您的最佳选择。
Scott Mitchell 写了一篇关于实现该模式的综合教程:Implementing Optimistic Concurrency
【讨论】:
【参考方案2】:一个经典的做法如下:
为每个表添加一个“锁定”的布尔字段。 默认设置为 false。当用户开始编辑时,你这样做:
锁定行(如果不能锁定行,则锁定整个表) 检查您要编辑的行上的标志 如果标志为真,那么 通知用户他们目前无法编辑该行 其他 将标志设置为真释放锁
保存记录时,将标志设置回false
【讨论】:
这还不够好,如果设置lock=true,如果应用程序或浏览器崩溃,则记录永久死锁。 好点,@SilverNight - 你能发布正确的解决方案吗? 对于这种情况(应用程序/浏览器崩溃),您可以在应用程序中添加 ForceUnlock 方法,这将强制将 lock 设置为 False。 这波白旗解决方案“解决并发修改很难所以我要退出”【参考方案3】:@Mark Harrison:SQL Server 不支持该语法 (SELECT ... FOR UPDATE
)。
SQL Server 等价物是SELECT
语句提示UPDLOCK
。
更多信息请参见SQL Server Books Online。
【讨论】:
【参考方案4】:-首先创建字段(更新时间)以存储上次更新记录 - 当任何用户选择记录保存选择时间时, 比较选择时间和更新时间字段 if(update time) > (select time) 表示另一个用户在选择记录后更新了这条记录
【讨论】:
【参考方案5】:SELECT FOR UPDATE 和等价物很好,只要您持有锁定的时间很短,但对于宏观数量(例如,用户已加载数据并且没有按“保存”,您应该使用上述乐观并发.(我一直认为这是错误的名称——它比“最后一位作家获胜”更悲观,后者通常是唯一考虑的其他选择。)
【讨论】:
【参考方案6】:另一种选择是测试您正在更改的记录中的值是否与您开始时的值相同:
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 存储过程的字段。
它还有一个优点是您不会锁定记录 - 因为我们都知道记录最终会在不应该被锁定时保持锁定......
【讨论】:
【参考方案7】:数据库将为您执行此操作。看看“select ... for update”,它就是为这种事情设计的。它会给你一个选定行的写锁,然后你可以提交或回滚。
【讨论】:
【参考方案8】:对我来说,最好的方式是拥有一个 lastupdate 列(timetamp 数据类型)。 选择并更新刚刚比较此值时 此解决方案的另一个进步是您可以使用此列来跟踪数据更改的时间。 我认为如果你只是创建一个像 isLock 这样的列来进行检查更新是不好的。
【讨论】:
以上是关于由多个用户编辑数据库记录的主要内容,如果未能解决你的问题,请参考以下文章