sql-server – 如何为多用户应用程序实现一个简单的锁机制?

我真的不想在这里重新发明井,所以我要求在多用户数据库应用程序中实现简单(行)锁机制的想法.

假设我有一个名为Products的表,当然有一个ID(PK),还有一个rowversion列(到目前为止还没有使用),我想只允许一个用户编辑一个特定的行.

当此用户正在编辑记录时(在“签入”之后),其他用户只能查看此记录(只读),但不能修改或删除它.当用户完成并保存记录(“结账”)时,该记录将再次可供其他用户编辑/删除.

我有一些想法(例如添加“状态”列,或者可能创建一个“锁定”表),但是如果“锁定用户”持有记录已经很长时间(也就是说他去了周末,他的电脑在编辑模式下打开).如果程序在客户端计算机上崩溃/系统断电,如何解锁记录…

我想知道是否有一个好的和相对简单的模式(可能包括SQL-Server功能)?

顺便说一句,我的客户端应用程序是Delphi / ADO(不是它非常相关).

最佳答案
我在应用程序中实现的简单解决方案….

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不同,则记录已被锁定.然后,我可以向用户显示一条消息,告知记录被锁定,使字段只读,禁用保存按钮,并告诉他们如果我愿意,谁可以锁定它.

转载注明原文:sql-server – 如何为多用户应用程序实现一个简单的锁机制? - 代码日志