首批通过分布式安全可靠测评,为关键业务系统打造
表级恢复任务卡住、无法取消问题
更新时间:2026-05-13 07:31
问题现象
表级恢复场景,表级恢复任务卡主,用户执行表级恢复取消命令 alter system cancel recover table dest_tenant_name,无法取消该任务。
关键诊断信息
触发条件
表级恢复期间,RS 出现双主,有一定概率触发。
事前巡检
无法通过事前巡检的方式规避。
事后诊断
出现表级恢复任务卡主,执行取消任务命令,任务无法取消现象后,可以通过错误日志排查和确认该问题。
根据关键字 get_recover_table_job_history_by_initiator和 multi value exist 获取 OBServer 日志。若出现以下内容的日志,则说明遇到这个问题。
[**-**-** *****] WDIAG [SHARE] get_recover_table_job_history_by_initiator (ob_recover_table_persist_helper.cpp**) [*****][T1_REST_SER][T*][*******] [lt=**][errcode=-4016] multi value exist(ret=-4016, sql=select * from __all_recover_table_job_history where initiator_tenant_id =* and initiator_job_id=**, exec_tenant_id=***)
问题原因
表级恢复期间,RS 出现双主状态,系统租户为目标租户下生成相应的表级恢复任务时,有概率导致表级恢复任务被重复地插入到租户的任务记录表 __all_recover_table_job 中,导致出现表级恢复任务卡主,无法取消掉的问题。
BUG 出现原因如下。
系统租户为目标租户下生成相应的表级恢复任务的过程可以简要概括。
读取目标租户的表级恢复任务表,校验对应任务不存在。
读取目标租户的表级恢复任务历史表,校验对应任务不存在。
将对应表级恢复任务插入到租户的表级恢复任务记录表中。
在 OceanBase 数据库 V4.2.1 BP1(oceanbase-4.2.1.1-101000062023103122)出现该问题的版本,上述过程同时允许多个线程访问(非排他),在 RS 出现双主状态时,有概率出现 2 个线程执行步骤 3,出现重复插入的情况。
对上述流程,加上排他锁和事务进行保护,这样就可以避免两个线程同时执行上述动作,避免异常情况发生。
导致表级恢复任务被重复地插入到租户的任务记录表 __all_recover_table_job 中。 表级恢复期间,系统租户在生成目标租户下面的表级恢复任务时,导致表级恢复任务记录被重复插入到目标租户的表级恢复任务记录表。
问题的风险及影响
导致表级恢复任务卡主、无法取消掉。租户后续将不能再执行表级恢复任务。
影响租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
影响版本
OceanBase 数据库企业版本 V4.2.1 GA(oceanbase-4.2.1.0-100000182023092722)及之后版本。
解决方法
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V4.2.1 BP2(oceanbase-4.2.1.2-102010012023120119)版本。
在 OceanBase 数据库企业版 V4.2.1 BP2(oceanbase-4.2.1.2-102010012023120119)之前的 V4.2.1 GA(oceanbase-4.2.1.0-100000182023092722)版本,需要通过修改内部表的方式,来让卡主的表级恢复任务正常结束。
具体步骤如下。
系统租户登录,检查内部表
表级恢复任务表 __all_recover_table_job,确认系统租户发起表级恢复任务卡主,记录卡主任务的 job_id 为 xx。系统租户登录,切换到表级恢复卡住的目标租户的 Meta 租户。
alter system change tenant meta_tenant_id;检查 Meta 租户的内部表
表级恢复任务历史表 __all_recover_table_job_history,确认由系统租户发起的(卡主的)表级恢复任务,在目标租户下存在两条失败的任务记录。select * from __all_recover_table_job_history where initiator_tenant_id=1 and initiator_job_id=xx;删除内部表
表级恢复任务历史表__all_recover_table_job_history中,2 个失败的表级恢复任务记录中任务编号 job_id 较大的任务记录。delete from __all_recover_table_job_history where initiator_tenant_id=1 and initiator_job_id=xx and job_id = yy;
例如,系统租户下查询到由系统租户发起的、卡主的表级恢复任务 job_id 是33;目标租户 Meta 租户下,查询到系统租户发起的,卡住的表级恢复任务对应有两条失败的任务记录,job_id 分别是 0 和 1。此时,将 job_id 编号较大的记录,从目标租户 Meta 租户的
__all_recover_table_job_history表中删除,系统租户发起的、卡主的表级恢复任务就能正常结束。警告
修改内部表存在一定的风险,请勿自行操作。如果需要修改,请联系 OceanBase 技术支持团队。
内部表
__all_recover_table_job和__all_recover_table_job_history参数补充说明如下。initiator_job_id和initiator_tenant_id用于关联表级恢复的父任务,由系统租户发起的用户租户的下的表级恢复任务,initiator_tenant_id=1和initiator_job_id是系统租户下的表级恢复任务 job_id;job_id 是租户的表级恢复任务的 job_id。
规避方式
无法回避。