我不确定的是如何确保在应用程序意外退出时(例如计算机意外关闭)数据库得到更新?此外,当应用程序通过用户关闭计算机退出时,应该如何更新它?我只想确保在没有人查看记录时不会出现记录被标记为锁定的情况。
我不确定的是如何确保在应用程序意外退出时(例如计算机意外关闭)数据库得到更新?此外,当应用程序通过用户关闭计算机退出时,应该如何更新它?我只想确保在没有人查看记录时不会出现记录被标记为锁定的情况。
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的连接,而不会对服务器产生任何负面影响。
using (RecordLockingThing myThing = new RecordLockingThing())
{
//DoStuff
}
//Now myThing is out of scope, and will have been disposed.
请确保您的RecordLockingThing
在处理方法中正确且安全地释放锁。
另一种策略可能是不标记要锁定的记录,而是将它们标记为已编辑(或增加修订号)。然后,您可以允许多个人打开记录。当有人提交编辑时,请让他们同时提交修订号,如果匹配,则提交编辑并增加修订版号,如果不匹配,则报告“空中碰撞”,然后丢弃编辑(不太友好),或尝试让用户合并记录。
如果相对于读取而言编辑较少,第二种策略在实践中将更有用,因为您永远不会阻止用户至少查看记录,并且不存在孤立锁的风险。
为了处理意外关机问题,我通常会给每个逻辑锁定一个过期时间;这可能意味着(例如)你需要一个 LockOwnerId
和一个 LockExpiry
列,但通常不是问题。如果用户仍然在屏幕上,你的应用程序可以随时 延长 锁定时间,但这意味着如果计算机突然断开网络连接,记录将在几分钟内自动变为可用状态。另一个选择是允许关键用户强制解除锁定。
关于用户终止应用程序的问题;只需跟踪您所拥有的锁并删除它们 ;p
我曾经在一个DMS应用程序中遇到过类似的问题,在服务器端我使用了一个会话对象,即活动用户的集合,每个客户端每5分钟更新一次会话对象。因此,如果一行被锁定并且锁定它的用户不再在会话对象中,则我会释放它。为了解锁,我在服务器端运行一个后台线程,每分钟扫描一次锁定的行。
我很惊讶没有人提到sp_getapplock及其类似功能。只要您保持与服务器的单个连接打开(并且锁由Session拥有而不是Transaction),则锁将得以维护。如果连接中断(例如客户端机器崩溃),则与SQL Server中的所有内部锁一样,锁将被释放。
本质上,这是一种使SQL Server为您的应用程序目的使用其内部锁定机制的方法。
正如我所说,它的一个小问题是您必须保持与服务器的连接打开。因此,对于最多50个客户端而言可能更合适,而不是涉及数千个客户端的情况。我还要补充另一个警告-我尚未使用这些功能构建生产系统。