如何使用信号量锁定表?

Posted

技术标签:

【中文标题】如何使用信号量锁定表?【英文标题】:How to use semaphore to lock table? 【发布时间】:2012-09-30 14:52:24 【问题描述】:

我想在事务执行时锁定 MDB 表以防止读取。我会使用dbDenyRead,但显然这是不可靠的,并不总是锁定表:

http://www.office-archive.com/32-ms-access/c2bd1a2553e79c60.htm

如何使用信号量解决方案来实现对表的虚拟锁定?

如果我将信号量存储在另一个表中,其中一行包含表名和将在事务结束时清除的进程/工作站 ID,我该如何防止以下顺序?

    进程 A 查询信号量表,发现它是空白的。 进程 B 查询信号量表,发现它是空白的。 进程 A 使用进程 A ID 更新信号量表。 进程 B 使用进程 B ID 更新信号量表。 进程 A 和 B 都执行事务(不是我想要的)。

请不要包含使用IF SQL 语句的答案,因为我的 JET-SQL 版本不能使用它。

【问题讨论】:

您打算如何处理“proc A 获得锁,proc A 开始在受保护的表中工作,proc A 崩溃”? @Damien_The_Unbeliever:如果 proc A 崩溃,那么它的事务将不会被提交并且它的锁将被释放,不是吗? 我不确定 - 如果您无法从系统中获得许多原子性保证,您似乎正在使用相当糟糕的技术,正如您所指出的那样。 @Damien_The_Unbeliever:我现在明白你的意思了:如果发生崩溃,信号量将如何被清除?信号量是否需要到期,比如 5 分钟? 【参考方案1】:

我不确定这是否会解决您的所有问题。但是使用非自动生成的主键创建一个表。如果可能,还使用某种检查/规则声明同一列,强制该列只能包含一个可能的值。

您现在有一个可以包含 0 或 1 行的表。要获得“信号量”,请在表中插入一行,具有单个固定的 PK 值。如果此插入成功,则您拥有信号量。如果插入由于主键冲突而失败,那么您没有获得信号量。关键是首先执行初步检查 - 只是尝试插入。

如果你的技术太烂以至于无法保证保持 PK 约束,那么你真的需要考虑改变技术。

如果您未能插入行,那么您可以开始定期轮询该表 - 以任何合适的时间间隔。


另一种选择是让表有一个自动编号的 PK 列 - 当您想要获取信号量时,在表中插入一行。然后,查询该表以找到具有最低 PK 列值的行。如果该行是您的 行,那么您现在拥有信号量。您仍然需要投票,但您实际上在此表中记录了“保留”。

与前一种情况一样,一旦您完成了受信号量保护的工作,您就可以从表中删除您的行。第二种方法应该“更公平”(因为每个进程都按照严格的请求顺序获得访问权限),但在实践中可能看起来更混乱。它确实依赖于所有进程保持“活跃”。

【讨论】:

PK 约束解决方案看起来是最好的选择。崩溃场景呢?

以上是关于如何使用信号量锁定表?的主要内容,如果未能解决你的问题,请参考以下文章

如何找到信号量未锁定的原因

文件锁定与信号量

使用 Saxon 时如何停止样式表文件锁定?

如何在 postgres 中使用“更新跳过锁定”而不锁定查询中使用的所有表中的行?

Unity-新增锁定输入如何操作?

如何使用 Entity Framework 在读取时锁定表?