【发布时间】:2017-03-01 22:53:39
【问题描述】:
我使用的是 OpenEdge 11.1 版。我偶尔会在运行时收到以下错误消息:
10 秒的锁定等待超时已过期 (8812)
根据我的调试日志,该错误发生在各种类中,这使得调试异常困难。有什么方法可以在调试日志中打印一些有关错误的详细信息,例如锁定了哪条记录?
【问题讨论】:
标签: openedge progress-4gl progress-db
我使用的是 OpenEdge 11.1 版。我偶尔会在运行时收到以下错误消息:
10 秒的锁定等待超时已过期 (8812)
根据我的调试日志,该错误发生在各种类中,这使得调试异常困难。有什么方法可以在调试日志中打印一些有关错误的详细信息,例如锁定了哪条记录?
【问题讨论】:
标签: openedge progress-4gl progress-db
这通常意味着您正在尝试锁定已锁定的记录。 OpenEdge 等待 10 秒(或 -lkwtmo 启动参数指定的时间)然后放弃,将错误留在日志中。
要找出哪些记录被锁定,请查看 _Lock 表。这是一张隐藏的桌子;您可以通过进入数据字典并选择查看 - 显示隐藏表来查看其架构。 _Lock 记录包含诸如记录 ID、锁定类型(共享/独占)、锁定它的用户等信息。您可以使用此代码将锁定表转储到文件中。希望它可以帮助您追踪锁定的记录。
OUTPUT TO VALUE("locktable.txt").
FOR EACH _Lock WHERE _Lock._Lock-RecID <> ? NO-LOCK:
FIND _File WHERE _File._File-Number = _Lock._Lock-Table NO-LOCK NO-ERROR.
PUT UNFORMATTED
_Lock._Lock-Name " "
_Lock._Lock-Usr " "
_File._File-Name " "
_Lock._Lock-RecID " "
_Lock._Lock-Type " "
_Lock._Lock-Flags
SKIP.
END.
OUTPUT CLOSE.
要捕获锁定错误,请将NO-WAIT 添加到您的FIND 语句中:
FIND FIRST <TableName> WHERE ... EXCLUSIVE-LOCK NO-WAIT NO-ERROR.
IF LOCKED(<TableName>) THEN ...
然后您可以在IF-THEN 语句中添加调试代码。
【讨论】:
FIND 上使用NO-WAIT,然后检查LOCKED()。我已将其添加到我的答案中。
它总是取决于上下文,但 10 秒非常非常短!我习惯了1800秒呵呵。这是一个可以更改的数据库启动系统参数。
这是一家拥有数千名用户的大公司。从来没有找到完全控制锁定问题的好方法,但我所做的是向 Unix 脚本添加一些逻辑,以 24/24 监控一堆东西。
我实现的是至少在锁定超时实际发生之前向我们的帮助台发送警报。
使用 _lock、_file (table) 和 _user 您可以获得关于被锁定的用户、什么表和什么记录的非常详细的信息。
我们的情况可能有所不同,但我们不关心 1 个用户将记录锁定 10 分钟......但我们希望找到锁定另一个用户等待的记录的用户。因为当锁定超时发生时,它也会撤消取决于上下文可能会出现问题的事务!
所以我们会记录一个锁,如果它超过 10 分钟没有移动,我们会触发警报,发送我们可以发送的所有信息。包括其他用户为同一记录“战斗”。更常见的情况不是问题在于用户正在更新关键表并出于某种原因使屏幕保持打开状态。
【讨论】: