首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为多用户应用程序实现简单的锁机制?

如何为多用户应用程序实现简单的锁机制?
EN

Stack Overflow用户
提问于 2014-01-22 13:29:48
回答 2查看 5.2K关注 0票数 7

我真的不想在这里重新发明井,所以我想知道在多用户DB应用程序中实现简单的(行)锁机制的想法。

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

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

我有一些想法(比如添加一个"status“列,或者创建一个"lock”表),但是如果“锁定用户”保存记录很长时间(假设他去了一个周末并让他的计算机处于编辑模式中),也要考虑一些问题。此外,如果程序崩溃/客户端计算机上的系统断电,如何解锁记录.

我想知道这是否有一个好的和相对简单的模式(其中可能包括Server特性)?

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-22 14:02:28

我在应用程序中实现的一个简单的解决方案..。

代码语言:javascript
复制
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() RecordIdVARCHAR,因为我要锁定的表中有主键(不是我的选择)。另外,这个表有明显的索引。

代码语言:javascript
复制
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是不同的,记录已经锁定。然后,我可以向用户显示一条消息,通知记录被锁定,使字段只读,禁用保存按钮,并告诉他们谁有锁,如果我愿意的话。

票数 4
EN

Stack Overflow用户

发布于 2014-01-22 16:16:29

有了时间戳,你就可以“作弊”了。工作流程如下所示:

  1. 将行(包括时间戳)读入内存
  2. 让用户进行一些编辑,跟踪新旧值。
  3. 用户点击“保存”
  4. 再次读取行的时间戳(在防止不可重复读取的隔离级别中)
    1. 如果最近读取的时间戳与旧时间戳相同,则使用用户更改的值更新行并提交。
    2. 如果最近读取的时间戳与旧的时间戳不同,则可以尝试“合并”更改(即,如果更改了一组完全不相交的属性,则这两个更改是兼容的)。如果有任何重叠,请警告用户并不允许保存。

这样就行了。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21284271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档