我真的不想在这里重新发明井,所以我想知道在多用户DB应用程序中实现简单的(行)锁机制的想法。
假设我有一个名为Products的表,它当然有一个ID (PK),还有一个rowversion列(到目前为止还没有使用),我希望只允许一个用户编辑特定的行。
当该用户正在编辑记录时(在“签入”之后),其他用户只能查看此记录(只读),但不能修改或删除它。当用户完成并保存记录(“签出”)时,该记录将再次用于其他用户的编辑/删除。
我有一些想法(比如添加一个"status“列,或者创建一个"lock”表),但是如果“锁定用户”保存记录很长时间(假设他去了一个周末并让他的计算机处于编辑模式中),也要考虑一些问题。此外,如果程序崩溃/客户端计算机上的系统断电,如何解锁记录.
我想知道这是否有一个好的和相对简单的模式(其中可能包括Server特性)?
顺便说一句,我的客户端应用程序是Delphi/ADO (并不是说它非常相关)。
发布于 2014-01-22 14:02:28
我在应用程序中实现的一个简单的解决方案..。
CREATE TABLE RecordLocks(
[RecordId] [varchar](8) NOT NULL,
[UserName] [varchar](100) NOT NULL,
[datetimestamp] [smalldatetime] NOT NULL,
[PC] [varchar](100) NOT NULL
)
GOdatetimestamp默认为GetDate() RecordId是VARCHAR,因为我要锁定的表中有主键(不是我的选择)。另外,这个表有明显的索引。
CREATE PROCEDURE usp_LockRecord @RecordId VARCHAR(8), @UserName VARCHAR(100), @ComputerName VARCHAR(100)
AS
BEGIN
BEGIN TRAN;
DELETE FROM RecordLocks WHERE DATEDIFF(HOUR, datetimestamp, GETDATE()) > 2;
IF NOT EXISTS (Select * from RecordLocks WHERE RecordId = @RecordId)
INSERT INTO RecordLocks (RecordId, username, PC) VALUES (@RecordId, @UserName, @ComputerName);
Select * from RecordLocks WHERE RecordId = @RecordId;
COMMIT TRAN;
END
GO第一次删除并记录2小时以上(更改为适合)
检查是否已经锁定要锁定的记录,如果没有,则插入锁。
使用我们感兴趣的RecordId选择记录。
然后在调用代码中检查锁是否成功。如果来自select的用户名和PC匹配,那么刚才在锁中传递的数据是成功的。如果用户名匹配,但PC不匹配,则同一用户在另一台机器上打开记录。如果用户名不匹配,则另一个用户已经打开它。如果该记录不成功,我将向用户显示一条消息,即该记录目前已被JoeB锁定在工作站XYZ上。
当用户保存记录或导航离开时,只需删除记录锁。
我相信还有其他的方法,但这对我来说很好。
更新
只有在不存在记录的情况下才会插入记录。下面的选择将返回一个记录。如果用户名和/或pc与您试图插入的数据不同,则记录已经被另一个用户(或其他计算机上的同一用户)锁定。所以一次电话就可以做到一切(可以这么说)。因此,如果我打了一个电话,Exec usp_LockRecord(1234, 'JoeB', 'Workstation1'),我得到的记录与数据匹配,我已经成功地锁定了该记录。如果用户名和/或我得到的PC是不同的,记录已经锁定。然后,我可以向用户显示一条消息,通知记录被锁定,使字段只读,禁用保存按钮,并告诉他们谁有锁,如果我愿意的话。
发布于 2014-01-22 16:16:29
有了时间戳,你就可以“作弊”了。工作流程如下所示:
这样就行了。
https://stackoverflow.com/questions/21284271
复制相似问题