我真的不想在这里重新发明,所以我要求在多用户数据库应用程序中实现简单(行)锁机制的想法。
假设我有一个名为Products
的表,当然有一个ID(PK),还有一个rowversion
列(目前尚未使用),我只想允许一个用户可以编辑特定行。
虽然此用户正在编辑记录(在“签入”之后),但其他用户只能查看此记录(只读),但不能修改或删除它。当用户完成并保存记录(“结账”)时,该记录将再次可供其他用户编辑/删除。
我有一些想法(例如添加“状态”列,或者可能创建“锁定”表),但是如果“锁定用户”长时间持有记录也会有所考虑(假设他去了一个周末,让他的电脑在编辑模式下打开)。如果程序在客户端计算机上崩溃/系统断电,如何解锁记录...
我想知道是否有一个好的相对简单的模式(可能包括SQL-Server功能)?
BTW,我的客户端应用程序是Delphi / ADO(不是很相关)。答案 0 :(得分:4)
我在应用程序中实现的简单解决方案......
CREATE TABLE RecordLocks(
[RecordId] [varchar](8) NOT NULL,
[UserName] [varchar](100) NOT NULL,
[datetimestamp] [smalldatetime] NOT NULL,
[PC] [varchar](100) NOT NULL
)
GO
datetimestamp
的默认值为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没有,则同一用户在另一台计算机上打开记录。如果用户名与其他用户不匹配则已打开。如果用户失败,我会向用户显示一条消息.E此记录当前由JoeB在工作站XYZ上锁定。
当用户保存记录或导航时,只需删除记录锁定。
我确定还有其他方法,但这对我有用。
<强>更新强>
只有在不存在记录时才会插入记录。以下选择将返回记录。如果用户名和/或pc与您尝试插入的数据不同,则该记录已被另一个用户(或另一台计算机上的同一用户)锁定。所以一个电话就可以了(可以这么说)。因此,如果我拨打电话Exec usp_LockRecord(1234, 'JoeB', 'Workstation1')
并且我收到的记录与该数据匹配,那么我已成功锁定该记录。如果我回来的用户名和/或PC不同,则记录已被锁定。然后,我可以向用户显示一条消息,告知记录被锁定,使字段只读,禁用保存按钮,如果我愿意,告诉他们谁有锁。
答案 1 :(得分:2)
有了时间戳,你可以逃脱“作弊”。工作流程看起来像这样:
应该这样做。