编辑多个用户的数据库记录
我已经设计了数据库表(在MS SQL服务器上已标准化),并为应用程序创建了一个独立的Windows前端,少数用户将使用该前端来添加和编辑信息。我们将添加一个Web界面,以便以后在整个生产区域进行搜索。
我担心如果两个用户开始编辑同一条记录,那么最后提交更新的将是"赢家",并且重要的信息可能会丢失。我想到了许多## 解决方案,但是我不确定是否会造成更大的麻烦。
不执行任何操作,希望两个用户永远不会同时编辑同一条记录。 -可能永远不会被遮挡,但如果会呢?编辑例程可以存储原始数据的副本以及更新,然后在用户完成编辑后进行比较。如果它们不同,请显示用户并确认更新-将需要存储两个数据副本。添加最后更新的DATETIME列,并在我们更新时检查它是否匹配,否则请显示差异。 -在每个相关表中都需要新列。创建一个编辑表,该表在用户开始编辑将要检查的记录时进行注册,并防止其他用户编辑同一记录。 -需要认真考虑程序流程,以防止死锁和记录在用户退出程序时被锁定。
有没有更好的## 解决方案,或者我应该选择其中一种?
解决方案:
如果我们希望很少发生冲突,那么乐观并发可能是我们最好的选择。
Scott Mitchell撰写了有关实现该模式的综合教程:
实现乐观并发
数据库将为我们执行此操作。看" select ... for update",它是专门为这种事情而设计的。它将为我们提供对选定行的写锁定,然后我们可以提交或者回滚。
@ Mark Harrison:SQL Server不支持该语法(" SELECT ... FOR UPDATE")。
SQL Server的等效项是SELECT语句提示" UPDLOCK"。
有关更多信息,请参见SQL Server联机丛书。
另一个选择是测试要更改的记录中的值是否与开始时的值相同:
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语句并将新字段和旧字段传递给存储过程。
它还具有我们不锁定记录的优点,因为我们都知道,当不应该使用记录时,记录最终将保持锁定状态。
SELECT FOR UPDATE和等效项很不错,只要我们在微观时间内保持该锁定,但是对于宏观量而言(例如,用户已加载数据且未按"保存",则应如上所述使用开放式并发。)我总是认为自己的名字被误认为比"最后一位作家获胜"更为悲观,后者通常是唯一考虑的其他选择。)
经典方法如下:
向每个表添加一个"锁定"的布尔字段。默认情况下将其设置为false。锁定行(如果无法锁定,则锁定整个表),如果标志为true,则检查要编辑的行上的标志,然后通知用户当前无法编辑该行,否则将标志设置为真的
当用户开始编辑时,我们可以执行以下操作:
{分块}
释放锁
保存记录时,将标志设置回false