繁体   English   中英

数据库记录锁定

[英]database record locking

我有一个服务器应用程序和一个数据库。 服务器的多个实例可以同时运行,但所有数据都来自同一个数据库(在某些服务器上是postgresql,在其他情况下是ms sql server)。

在我的应用程序中,执行的过程可能需要数小时。 我需要确保这个过程一次只执行一个。 如果一个服务器正在处理,则在第一个服务器实例完成之前,其他任何服

该过程取决于一个表(让我们称之为'ProcessTable')。 我所做的是,在任何服务器启动长达一小时的过程之前,我在ProcessTable中设置一个布尔标志,表示该记录被“锁定”并正在处理(并非该表中的所有记录都被处理/锁定,所以我需要专门标记流程所需的每条记录)。 因此,当前一个实例仍在处理时,当下一个服务器实例出现时,它会看到布尔标志并抛出异常。

问题是,两个服务器实例可能几乎同时被激活,并且当两者都检查ProcessTable时,可能没有设置任何标志,但是两个服务器实际上都在“设置”标志的过程中但是因为事务尚未提交任何一个进程,任何进程都不会看到其他进程完成锁定。 这是因为锁定机制本身可能需要几秒钟,因此存在两个服务器可能仍然能够同时处理的机会窗口。

看来我需要的是我的'Settings'表中的一条记录,它应该存储一个名为'LockInProgress'的布尔标志。 因此,即使服务器可以锁定ProcessTable中所需的记录,它首先必须通过检查Settings表中的'LockInProgress'列来确保它具有完全的权限来进行锁定。

所以我的问题是,如何阻止两台服务器同时修改设置表中的LockInProgress列?或者我是否以错误的方式处理此问题?

请注意,我需要支持postgresql和ms sql server,因为有些服务器使用一个数据库,而有些服务器使用另一个。

提前致谢...

如何首先获取记录锁定然后更新记录以显示“已锁定”。 这将避免第二个实例成功获得锁定,从而更新记录失败。

重点是确保锁定并更新为一个原子步骤。

创建一个存储过程来解锁,并在“可序列化”隔离下运行它。 这将保证在任何给定时间只有一个进程可以获取资源。

请注意,这意味着尝试获取锁定的第二个进程将阻塞,直到第一个进程释放它。 此外,如果您必须以这种方式获得多个锁,请确保该过程的设计保证将以相同的顺序获取和释放锁。 这将避免死锁情况,其中两个进程在等待彼​​此释放锁时保持资源。

除非你不能处理你的其他进程阻塞,否则这可能比试图实现'test and set'语义更容易实现和更强大。

我一直在考虑这个问题,我认为这是最简单的做事方式; 我只是执行这样的命令:

update settings set settingsValue = '333' where settingsKey = 'ProcessLock' and settingsValue = '0'

'333'将是每个服务器进程获得的唯一值(基于日期/时间,服务器名称,+随机值等)。

如果没有其他进程锁定表,则settingsValue将= = 0,该语句将调整settingsValue。

如果另一个进程已经锁定了该表,那么该语句将成为无操作,并且没有任何内容被修改。

然后我立即提交交易。

最后,我重新查询表的settingsValue,如果它是正确的值,那么我们的锁成功,我们继续,否则抛出异常,等等。当我们完成锁定后,我们将值重新设置为到0。

由于我正在使用SERIALIZATION交易模式,我无法看到这导致任何问题...如果我错了请纠正我。

暂无
暂无

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

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