Progress运行存储过程提示-s stack exceeded告警问题求助
你遇到的是OpenEdge ABL的锁等待超时错误,触发原因是你加了EXCLUSIVE-LOCK的目标记录,在数据库设置的锁等待阈值内被其他会话持有,无法被当前会话获取。以下是常见触发原因和修复方案:
触发原因1:其他并行会话持有目标记录锁
你操作的V_Acct表对应记录,可能同时被其他业务流程、定时任务、人工操作持有排他锁,你的会话等待超时触发报错。
修复方案:在FOR EACH语句中添加NO-WAIT参数,获取锁失败时跳过对应记录并留痕,后续批量重试:
/* 仅展示修改后的FOR EACH部分,其余逻辑保持不变 */ FOR EACH V_Acct WHERE V_Acct.Company = '123' AND V_Acct.ReceiptType = 'U' AND V_Acct.ReferenceNr = integer(TRIM(ENTRY(1,cData,';'))) AND V_Acct.xInfo = '' EXCLUSIVE-LOCK NO-WAIT: IF LOCKED(V_Acct) THEN DO: /* 可自行调整为写入日志文件的逻辑,方便后续重试 */ MESSAGE "获取锁失败,ReferenceNr:" TRIM(ENTRY(1,cData,';')) VIEW-AS ALERT-BOX WARNING. NEXT. END. V_Acct.xInfo = 'VGF00000000000000'. END.
触发原因2:事务粒度过大
当前代码所有修改都在一个隐式大事务中,所有修改过的记录锁都会持有到整个循环结束才释放,数据量较大时锁持有时间过长,大幅提升冲突概率。
修复方案:按批次提交事务,缩短锁持有时间:
/* 头部添加计数变量 */ DEFINE VARIABLE iCount AS INTEGER NO-UNDO INITIAL 0. repeat: if keyfunction(lastkey) = "end-error" then leave. process events. import unformatted cData. iCount = iCount + 1. FOR EACH V_Acct WHERE V_Acct.Company = '123' AND V_Acct.ReceiptType = 'U' AND V_Acct.ReferenceNr = integer(TRIM(ENTRY(1,cData,';'))) AND V_Acct.xInfo = '' EXCLUSIVE-LOCK: V_Acct.xInfo = 'VGF00000000000000'. END. /* 每处理100条提交一次,可根据实际业务调整批次大小 */ IF iCount MOD 100 = 0 THEN DO: COMMIT. iCount = 0. END. END. /* 循环结束提交剩余批次 */ COMMIT.
触发原因3:查询索引缺失
如果V_Acct表没有覆盖Company、ReceiptType、ReferenceNr、xInfo的联合索引,查询会扫描大量不匹配的记录并加锁,额外增加锁冲突概率。
修复方案:联系DBA添加对应查询索引,缩小锁定的记录范围。
内容的提问来源于stack exchange,提问作者Smokus
相关产品推荐
相关产品推荐

