Progress ABL,如何确定哪个最终用户正在锁定记录并显示给正在锁定记录的其他最终用户?

Progress ABL, How to determine which end-user is locking a record and display to other end-users who is locking the record?

我意识到 Progress ABL 有这样做的自然倾向:

By default, Progress displays the message: in use by on . Wait or choose CANCEL to stop. (2624)

This 2624 message provides information, but it is not usually what is wanted because users do not have a chance to commit changes or proceed without the STOP condition. Then they are returned to the startup procedure.

但是,我希望能够在 if ______ 锁定之后显示哪个正在锁定记录,然后执行以下操作: 显示和特定记录锁定

我确实在这篇 post 文章底部的文章中找到了有关使用 VST _Lock 的信息,但是 Progress 文档逐字说明了这一点,"Note: Use caution querying the _Lock table; frequent access can consume large quantities of system resources and negatively impact performance." 是否有替代方法或最佳实践?任何帮助将不胜感激。

https://knowledgebase.progress.com/articles/Article/P182366

我假设您已经熟悉 find ... exclusive-lock/share-lock no-wait no-error 因为如果不使用 no-wait 就无法使用锁定功能。

查询 _lock 可能没有评论说的那么糟糕。您只会在用户遇到锁定冲突时偶尔这样做。此外,性能在很大程度上取决于当前锁定的条目总数。

重要的是根据 Progress 版本以正确的方式查询 _lock。

重复my answer to a similar question:

  • _LOCK 始终具有 -L 中给定的完整条目数,无论当前存在多少个锁。
  • 在 11.4 之前的版本中,字段没有索引,但所有使用的锁都在 table 的开头,因此您可以使用

    FOR EACH _Lock NO-LOCK:
      IF _Lock._Lock-Usr = ? THEN LEAVE.
    

    (_Lock._Lock-Name = ? 也可以)。请参阅 http://knowledgebase.progress.com/articles/Article/P161995(显然,对于非常大的锁 table 或许多锁,这在实践中并非如此。但这可能是您可以做的最好的事情,因为扫描整个锁 table 确实需要一些时间时间。)

  • 在 11.4 和 11.5 中,填充的条目不再位于开头,因此旧代码会给出错误的结果(请参阅 http://knowledgebase.progress.com/articles/Article/000056304,这已在 11.5.1 中修复)。幸运的是扫描锁 table 现在快多了所以你可以使用

    FOR EACH _Lock NO-LOCK WHERE _Lock-Recid <> ?:
    

    在同一篇文章中提到。从技术上讲,这不是用索引实现的。 (索引不适用于 <> 运算符。)

  • 从 11.5 开始,两种变体都应该可以工作,但带有 where-phrase 的较新变体应该更快。

我很同情向用户提供有关谁持有锁的好消息的愿望。但是 kbase 不是在开玩笑。以这种方式使用 _LOCK 是一个非常糟糕的主意。

11.4+ 使它不那么糟糕,但在大型生产系统上仍然是一件非常痛苦的事情。

在具有默认锁 table 大小 (-L 8192) 的小型系统上,它将显示为 "ok"。在具有大锁 table(1M 以北的 -L 值很常见)并且使用大量锁的大型活动系统上,您将获得非常非常不同且非常负面的体验。

更好的解决方案可能是查看 "blocked users":

for each dictdb._Connect no-lock
    where _Connect-usr <> ?
      and _Connect-wait <> " -- ":  /* there are spaces around the '--' */

  display _Connect.

end.

这会快得多,并且可能会告诉您您需要知道的一切。

如果你要扫描 _LOCK 而不管 kbase 的警告,至少在你的循环中加入一些逻辑来跟踪它花费了多长时间,如果它变得太长则退出。这样的事情可能是一个好的开始:

etime( yes ).

for each dictdb._Lock where _Lock._Lock-usr <> ? and _Lock._Lock-recid <> ?:

  if etime > 500 then leave.

  /* whatever ... */

end.