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

Oracle更新CLOB列遇ORA-22920错误:行未锁定问题求助

ORA-22920: row containing the LOB value is not locked 错误分析与修复

错误原因

你的存储过程触发该错误的核心问题有两点:

  1. 行锁丢失:首次执行UPDATE设置EMPTY_CLOB()后,未锁定目标行;且循环内部每次执行COMMIT,会直接释放事务锁,导致后续写入CLOB时,目标行已无锁可用。
  2. 无效的CLOB引用逻辑:循环中重复执行SELECT获取CLOB引用,不仅效率低下,且COMMIT后之前的CLOB引用会失效,无法继续写入。

修复方案

修改存储过程,确保行锁持续持有至CLOB写入完成,同时优化CLOB引用的获取逻辑:

CREATE OR REPLACE PROCEDURE update_clob (
  p_company_id       NUMBER,
  p_table_name       VARCHAR2,
  p_column_name      VARCHAR2,
  p_clob_content     CLOB) IS

v_clob_ref           CLOB;
v_amount             NUMBER;
v_offset             NUMBER;
v_length             NUMBER;
v_content            VARCHAR2(4000);
v_update             VARCHAR2(32000);

BEGIN
  v_offset    := 1;
  v_amount    := 4000;
  v_length    := DBMS_LOB.GETLENGTH(p_clob_content);

  -- 初始化CLOB并同时获取带锁的引用
  v_update    := '
    UPDATE ' || p_table_name || '
    SET ' || p_column_name || ' = EMPTY_CLOB()
    WHERE company_id = :company_id
    RETURNING ' || p_column_name || ' INTO :clob_ref';

  EXECUTE IMMEDIATE v_update USING p_company_id, OUT v_clob_ref;

  -- 循环写入CLOB片段,全程保持行锁
  WHILE v_offset <= v_length LOOP
    v_content := DBMS_LOB.SUBSTR(p_clob_content, v_amount, v_offset);
    DBMS_LOB.WRITEAPPEND(v_clob_ref, LENGTH(v_content), v_content);
    v_offset := v_offset + v_amount;
  END LOOP;

  -- 所有写入完成后统一提交
  COMMIT;

END update_clob;

关键修改说明

  • 用UPDATE ... RETURNING ... INTO:一次性完成CLOB初始化和行锁定,直接获取带锁的CLOB引用,避免后续单独查询。
  • 移除循环内的COMMIT:将提交操作移至循环结束后,确保整个CLOB写入过程中行锁持续有效。
  • 取消重复SELECT:复用首次获取的CLOB引用,避免无效查询和引用失效问题。

额外建议

为避免SQL注入风险,建议对传入的表名、列名做合法性校验:

p_table_name := DBMS_ASSERT.SIMPLE_SQL_NAME(p_table_name);
p_column_name := DBMS_ASSERT.SIMPLE_SQL_NAME(p_column_name);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 09:43:20