当记录被锁定时,如何安全地退出DBMS?

时间:2010-11-15 11:48:03

标签: c# sql-server database

我是一个业余爱好者,但已经做了一段时间。我正在编写一个用于工作的小型文档管理应用程序(在c#中)。当用户打开记​​录时,我会更新它以指示它当前已被锁定以进行编辑。

我不确定的是当应用程序不安全地退出时如何确保数据库得到更新(例如,计算机意外关闭)?此外,当应用程序通过用户关闭的计算机退出时,我应该如何更新它?我只是想确保在没有人查看记录时我最终没有将记录标记为已锁定。

5 个答案:

答案 0 :(得分:2)

以下是通常使用SQL Server完成的操作。开发人员发布的“记录锁”与客户端 - 服务器体系结构无关。您将共享文件体系结构与客户端 - 服务器体系结构混淆。

确保该表具有时间戳列(由数据库引擎自动更新)。

读入您要编辑的行。将行中的时间戳放在变量中。

更新语句如下所示:

update myTable
set col = {some value}
where id = {your id}
AND
timestampcolumn = {the timestamp the row had when you read it in}

如果有人在您读入该行后更改了该行,则它将具有不同的时间戳,并且没有记录符合您的WHERE子句条件,因此您的更新将失败。然后你可以决定做什么。

当您使用SQL-Server(或Oracle或任何真正的客户端 - 服务器架构)时,您可以在客户端PC上拔下插头,而不会对服务器产生任何负面影响。

答案 1 :(得分:1)

在C#中,您可以使用try-catch-finally块,并在finally中执行整理。 (无论如何都应该执行。)

你可以通过创建一个实现IDisposable的类来获得锁定,并在调用disposing方法时释放它。然后每当你使用该类(获得锁定)时,请输入一个使用块

using (RecordLockingThing myThing = new RecordLockingThing())
{
    //DoStuff
}
//Now myThing is out of scope, and will have been disposed.

请确保您的RecordLockingThing在处置方法中正确安全地释放锁定。

另一种策略可能不是标记记录以在打开时锁定它们,而是将它们标记为已编辑(或增加修订号)。然后,您可以允许多个人打开记录。当有人提交编辑时,让他们也提交修订号,如果匹配,提交编辑并增加修订,如果没有,报告“空中碰撞”,并丢弃编辑(不是很友好),或尝试并让用户合并记录。

如果编辑与读取相比相当罕见,那么第二种策略在实践中会更有用,因为您永远不会阻止用户至少查看记录,并且不存在孤立锁定的风险。

答案 2 :(得分:0)

为了处理意外关机的问题,我通常会给每个逻辑锁一个到期日;这可能意味着(例如)您需要LockOwnerIdLockExpiry列,但这通常不是问题。如果用户仍在屏幕中,您的应用程序始终可以扩展锁定,但这意味着如果计算机只是从网络中删除,则记录将在几分钟内隐式变为可用。另一种选择是允许关键用户粉碎锁。

重新启动用户终止应用;只需跟踪您拥有的锁定并将其删除; p

答案 3 :(得分:0)

我在DMS应用程序中遇到了类似的问题,在服务器端我使用了会话对象,活动用户的集合,每个客户端每5分钟更新一次会话对象。因此,如果一行被锁定并且锁定它的用户不再在会话对象中,那么我将其释放。为了解锁这个问题,我在服务器端运行一个后台线程,每分钟扫描一次锁定的行。

答案 4 :(得分:0)

我很惊讶没有人提到sp_getapplock,而且是亲属。如果您保持对服务器的单个连接打开(并且锁由Session而不是Transaction拥有),则将保持锁定。如果连接中断(例如客户端计算机崩溃),那么与SQL Server中的所有内部锁一样,锁将被释放。

基本上,它是让SQL Server使用内部用于应用程序的相同锁定机制的一种方法。

正如我所说,一个小问题就是你必须保持与服务器的连接打开。因此,或许更适合50个客户,而不是如果你有1000个客户参与。我还要补充一点 - 我没有使用这些设施建立生产系统。