You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不同数据库客户端连接方式下Procedure Locking差异的原因咨询

问题背景与现象

我创建了如下测试存储过程:

CREATE OR ALTER PROCEDURE tmp_fab
RETURNS (dummy INTEGER) AS
BEGIN
    dummy = 1;
    suspend;
END

随后客户端A执行以下SQL调用该存储过程:

SELECT *
FROM tmp_fab

当客户端B尝试修改该存储过程时(此时客户端A的事务仍活跃,未提交/回滚),行为会因客户端B的数据库连接方式不同而产生差异:

修改失败场景

尝试执行如下修改语句:

CREATE OR ALTER PROCEDURE tmp_fab
RETURNS (dummy INTEGER) AS
BEGIN
    dummy = 2;
    suspend;
END

提交客户端B的事务时,报错信息如下:

Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
Lock conflict on no wait transaction.
Unsuccessful metadata update.
Object PROCEDURE "TMP_FAB" is in use.

出现该情况的连接方式:

  • 使用FireDAC Delphi组件(DriverName = FB)
  • 使用FIBPlus Delphi组件
  • 使用IBExpert(自带Firebird DLL)

修改成功场景

同样执行上述修改语句,提交客户端B的事务时可正常变更存储过程。

出现该情况的连接方式:

  • 使用isql
  • 使用DBeaver(基于JDBC)
  • 使用FireDAC Delphi组件(DriverName = ODBC)

原因分析

这种差异核心在于不同客户端驱动/工具对事务隔离级别、锁等待策略的默认设置不同,结合Firebird的元数据锁机制导致:

  1. 元数据操作的锁特性
    Firebird中修改存储过程这类元数据操作,需要获取对象的独占锁。当客户端A的活跃事务正在使用该存储过程时,会持有该对象的共享锁,此时客户端B的修改请求需要的独占锁会与共享锁产生冲突。

  2. 锁等待策略的差异

  • 报错的工具/驱动(如FireDAC FB、FIBPlus、IBExpert)默认使用NO WAIT(无等待)策略:一旦检测到锁冲突,立即抛出错误,不会等待锁释放。
  • 成功的工具/驱动(如isql、JDBC-based DBeaver、FireDAC ODBC)默认使用WAIT(等待)策略:会等待一段时间,直到客户端A的事务提交/回滚、锁释放后,再完成元数据修改。
  1. 事务隔离级别的辅助影响
    部分工具的默认隔离级别会延长共享锁的持有周期,比如高隔离级别(如REPEATABLE READ)会让客户端A的锁持有更久;而另一些工具会在元数据操作时自动切换到适配的隔离级别,配合等待策略,就能避开锁冲突。

内容的提问来源于stack exchange,提问作者Fabrizio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:35:22