简体   繁体   English

我可以将数据库记录标记为“正在使用”吗?

[英]Can I mark a database record as “in use”?

Let's say I have a table (let's call it myTable ) on a database server, and I'm writing a desktop client application that allows you to modify records in myTable. 假设我在数据库服务器上有一个表(我们称它为myTable ),并且我正在编写一个桌面客户端应用程序,该应用程序允许您修改myTable中的记录。 I don't want two users to be able to edit the same record, ie, if user A edits record 1 and user B tries to do the same, he gets notified that the record is currently "locked" by user A. 我不希望两个用户能够编辑相同的记录,即,如果用户A编辑记录1而用户B尝试执行相同的操作,则他会收到通知,通知说该记录当前已被用户A“锁定”。

I'm sure that this is a common problem, so I'm wondering if there is a canonical solution to it. 我敢肯定这是一个普遍的问题,所以我想知道是否有规范的解决方案。


There is an obvious solution, but it also has an obvious drawback: 有一个明显的解决方案,但也有一个明显的缺点:

  • Add a field inUseBy to myTable , set it to the user's name once the user starts editing the record, and clear it once the user finishes, eg 一个字段添加inUseBymyTable ,它一旦用户开始编辑记录设置为用户的姓名,清除它一旦用户完成,如

     function editRecord(recordId): begin transaction if (select lockedBy from myTable where id = recordId) is not empty: commit show "Sorry, record already in use by ..." else update myTable set lockedBy = current_user() where id = recordId commit show UI window to let user edit and update record update myTable set lockedBy = empty where id = recordId 

    Drawback: If user A's application crashes, the record stays locked. 缺点:如果用户A的应用程序崩溃,则记录保持锁定状态。

The following approach might seem suitable at a first glance, but won't solve the problem: 乍一看,以下方法似乎合适,但无法解决问题:

  • Use database locks to lock record 1. This will just cause user B to run into a timeout. 使用数据库锁来锁定记录1。这只会导致用户B超时。 I need to lock the record on the application level not on the database level. 我需要将记录锁定在应用程序级别而不是数据库级别。

A common approach is to use ROWVERSION for optimistic concurrency. 一种常见的方法是使用ROWVERSION进行乐观并发。

Rowversion is a datatype (Which you'd add as a new column) that updates when the row is updated. Rowversion是一种数据类型(您将添加为新列)在更新行时更新。

So, you select your row, including the rowversion column. 因此,选择行,包括rowversion列。 When you send your update back, you make sure the rowversions match - By doing your update and adding "WHERE Rowversion = TheRowversionIGotEarlier" and seeing if @@ROWCOUNT is not 0 - If it is zero, then you can assume someone has modified the row since you read it, and you can return that message to the user. 当您发回更新时,请确保行版本匹配-通过进行更新并添加“ WHERE Rowversion = TheRowversionIGotEarlier”并查看@@ ROWCOUNT是否不为0-如果为零,则可以假定有人修改了该行自从您阅读它以来,就可以将该消息返回给用户。

http://www.mssqltips.com/sqlservertip/1501/optimistic-locking-in-sql-server-using-the-rowversion-data-type/ http://www.mssqltips.com/sqlservertip/1501/optimistic-locking-in-sql-server-using-the-rowversion-data-type/

You're asking about pessimistic concurrency, and as this answer and the comment on your question say - Do consider optimistic concurrency. 您正在询问悲观并发,正如这个答案和对您的问题的评论所说-请考虑乐观并发。 Consider your model, how would it handle someone starting to edit a record then going to lunch? 考虑您的模型,它将如何处理某人开始编辑记录然后吃午餐的问题? Or if they never came back from lunch? 或者,如果他们从午餐后再也没有回来? What if a record has to be edited in the meantime, for a critical business reason? 如果出于关键的业务原因必须同时编辑记录怎么办?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM