首批通过分布式安全可靠测评,为关键业务系统打造
Oracle 模式通过一条 SQL 既加 Lob 列也加 not null 约束后,查询写入报错 4002,获取不到 Lob
更新时间:2026-05-21 09:16
问题现象
Oracle 模式下,通过一条 SQL 执行加 Lob 列且加 not null 约束的 DDL 之后,涉及 Lob 列的操作(查询/写入/DDL)都有可能失败,报错 Invalid Arguemnt(failed to check lob_tablet_id)。
比较多场景下的报错日志信息如下所示。
WDIAG [STORAGE] prepare_lob_tablet_id (ob_lob_persistent_adaptor.cpp:983) [8210][T1002_PX_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=12][errcode=-4002] failed to check lob_tablet_id(ret=-4002, param={tenant_id:1002, src_tenant_id:1002, ls_id:{id:1001}, tablet_id:{id:217092}, lob_meta_tablet_id:{id:0}, lob_piece_tablet_id:{id:0}, lob_locator…
关键诊断信息
触发条件
下面各操作按顺序出现的话,问题必现。
Oracle 模式。
对不含 Lob 对象的表,通过一条 SQL 执行加 Lob 列且加 not null 约束。
对表所包含的日志流执行切主操作。
关于 Lob 列的操作(查询/写入/DDL)会失败报错。
事前巡检
检查业务是否存在通过一条 SQL 既加 Lob 列也加 not null 约束。如果存在的话,需要替换成多条语句形式。
目前出问题场景涉及到的 Lob 类型有:clob、blob、json、sdo_geometry。
以 CLOB 类型位列,一条 SQL 既加 Lob 列也加 not null 约束的形式,命令如下。
ALTER TABLE ADD C1 CLOB NOT NULL; ALTER TABLE ADD C1 CLOB, ADD C2 NUMBER NOT NULL;检查业务是否执行过一条 SQL 既加 Lob 列也加 not null 约束的操作。如果存在的话,得需要尽量规避掉风险。
-- 查询出所有包含加 not null 列的操作 SELECT * FROM oceanbase.__ALl_VIRTUAL_DDL_OPERATION WHERE TENANT_ID=$ORACLE_TENANT_ID AND DDL_STMT_STR LIKE '%ALTER%ADD%NOT%NULL%'; -- 查看上述 DDL_STMT_STR 是否存在加 列的场景.
如果业务执行过上述风险 SQL 的话,那么可以这样运维规避掉。
如果业务不再需要 Lob 列了,删除 Lob 列是最简单且有效的方法。
如果业务需要 Lob 列,那么建议最好是在空闲时刻将该表数据重整,以规避风险。
在重整数据之前,尽量避免 Transfer 操作、切主操作。
空闲时刻重整数据的方式有(注意下面方法提及的操作会上表锁,阻塞写入 DML)。
执行 Offline DDL,可以把隐藏风险给彻底规避掉。
执行旁路导入到另外一张表上。
事后诊断
问题发生时,一般带有 failed to check lob_tablet_id 日志报错,查询 ALL_VIRTUAL_DDL_OPERATION.DDL_STMT_STR 以确认之前是否执行过一条 SQL 既加 Lob 列也加 not null 约束的操作。上述均命中的话,基本可以确认是本文档描述的问题了。
问题原因
内核 BUG。多源事务框架不支持在一个 Schema 变更事务内注册超过 1 个多源 Buffer。其中 Follower 节点会跳过处理第二个多源 Buffer,导致多源信息丢失。
Oralce 模式下一条 SQL 既加 Lob 列也加 not null 约束会走多源读写防御,需要注册第一个多源 Buffer 使得各节点感知到列数的增加。非 Lob 表转 Lob 表时,需要注册第二个多源Buffer以创建 Lob Tablet 并让主表 Tablet 感知到 Lob Tablet。显然跳过处理第二个多源 Buffer 会使得主表 Tablet 无法感知到 Lob tablet 的创建,之后 Lob 列上的查询/写入/DDL,无法通过主表 Tablet 查找到 Lob Tablet,触发失败报错。
问题的风险及影响
如果触发了这个 BUG,那么会导致无法通过主表 Tablet 寻找到 Lob Tablet,也就是说基于 Lob 列上的操作 (查询/写入/DDL等) 都会失败。
影响租户
影响 OceanBase 数据库中的 Oracle 租户,对于 SYS 租户和 MySQL 租户无影响。
影响版本
OceanBase 数据库企业版本 V4.2.1 BP3(oceanbase-4.2.1.3-103000052023122809)及之后版本、V4.2.2 BP1(oceanbase-4.2.2.1-101000012024030619)及之后版本。
解决方法及规避方式
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V4.2.1 BP8(oceanbase-4.2.1.8-108000052024072217)及之后版本、V4.2.4(oceanbase-4.2.4.0-100000252024070621)及之后版本。
确认命中文档中描述的问题时处理方法。
将日志流 Leader 切回到创建 Tablet 时刻的 Leader。
查询得到参与者信息。
将 Leader 切到其他 Follower 上,等待约 10s 切主成功后。如果原报错 SQL 重新执行成功,则暂时规避成功。
在暂时规避成功后,其他节点的主表 Tablet 仍然无法感知到
Lob Tablet。需要继续运维通过重整表数据,以彻底避免风险。--查询得到问题租户问题日志流的参与者信息 SELECT * FROM oceanbase.__ALL_VIRTUAL_LS_META_TABLE WHERE TENANT_ID=$TENANT_ID AND LS_ID=$LS_ID;
当问题 Tablet 触发过 Transfer 操作或者曾经的 Leader 永久下线了,那么方法 1 将无法奏效,此时需要通过 ObAdmin 方式 Dump 出所有宏块,将用户数据整理后再重新导入表。
规避方式
问题版本上不要通过一条 SQL 既执行加 Lob 列也加 not null 约束的操作,可以拆分成多条 SQL 执行。
查看
ALL_DDL_OPERATION检查 Oracle 租户下是否执行过通过一条 SQL 既加 Lob 列也加 not null 约束。如果执行过的话,需要在问题触发前,通过 Offline DDL/旁路导入等方式将表数据进行重整。