问题现象
执行 SQL 报错 ERROR 4012 (HY000): RPC session not found,或者执行内部 SQL 报错,从 OBServer 日志中看到报错返回了 -4067 。
只有在 OceanBase 数据库 V4.x 版本才存在这个问题,如果其它版本也遇到了 -4067 的报错,请先检查一下 SQL 的执行时间是不是已经达到 query_timeout 了。
关键诊断信息
触发条件
两种情况:
执行 SQL 的触发了远程执行,并且本地端处理 SQL 结果的时候存在耗时操作(执行 PL 语句的场景比较容易触发)。
表级恢复任务,
inner sql查询的表数据包含 LOB 列。
事前巡检
无 。
事后诊断
使用 TRACE_ID 过滤,搜索报错时间点的 observer.log 日志,如果有如下所示的
can't deliver request的报错,并且错误码是 -4067,这个日志所在的节点就是流式 RPC 的接收端。obs_180.38/observer.log.20240328161340855:793114:[2024-03-28 16:13:18.795761] WDIAG [SERVER] deliver_rpc_request (ob_srv_deliver.cpp:584) [1621790][pnio1][T0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=39][errcode=-4067] can't deliver request(然后在这个节点上,使用 TRACE_ID 过滤,搜索时间更靠前的日志,如果找到了 -4208 报错的日志,并且日志中打印的
wait_timeout=30000000这个的超时和租户的_stream_rpc_max_wait_timeout配置项一致(日志里面的 T1006 就是租户 id,没有改过这个配置项的话就是默认值 30000000),就可以确定是这个问题。ps.如果这两个值不一致,而且 wait_timeout=的值和 SQL 的 query_timeout 很接近,那通常都是 SQL 的 query_timeout 设置得太小了,这种情况也会导致流式 RPC 返回 -4067 报错,需要调大 query_timeout 。
obs_180.38/observer.log.20240328161340855:554163:[2024-03-28 16:10:08.926150] WDIAG [RPC.OBRPC] wait (ob_rpc_stream_cond.cpp:56) [1623597][T1006_L0_G0][T1006][YB420A7DB428-000613B3AF6B97AF-0-0] [lt=22][errcode=-4208] wait for next request failed(ret=-4208, sessid=1710511697238015) obs_180.38/observer.log.20240328161340855:554164:[2024-03-28 16:10:08.926170] WDIAG [RPC.OBRPC] flush (ob_rpc_processor_base.cpp:582) [1623597][T1006_L0_G0][T1006][YB420A7DB428-000613B3AF6B97AF-0-0] [lt=18][errcode=-4208] wait next packet fail, set req_ to null(ret=-4208, wait_timeout=30000000)从上面的
ob_rpc_stream_cond.cpp:56日志可以找到一个 session_id,使用这个 session_id 继续搜索日志,如下命令。grep -rn "1710511697238015" obs_180.38/observer.log.2024*输出内容如下:

找到
deliver_rpc_request这条日志的打印时间是 16:13:18,prepare (ob_rpc_stream_cond.cpp:40) 这条日志打印时间是 16:09:38,两个相差 220s ,如果要解决这个问题,需要将租户的_stream_rpc_max_wait_timeout配置项设得比这个相差值要大,从ret=-4208的报错日志可以确定租户 id,对应日志中高亮的 T1006,即 tenant_id 是 1006 。
问题原因
接收端在处理流式 RPC 请求的时候,在工作线程回包之后,处理不会结束而是会继续阻塞在 wait_for_next_request 上,等待源端发送下一个请求继续处理,直到工作线程没有包要回了或者源端发送了一个 abort 请求。但是如果源端网络异常或者进程被退出,abort 请求没有被发出去,就会导致处理端的工作线程一直 hung 在 wait_for_next_request,导致删除租户后 unit 长时间不释放,在 OceanBase 数据库 V4.2.1 BP2 版本上为了解决这个问题,引入了租户工作线程处理流式 RPC 的时候等待下一个请求的最大超时时间的配置项 _stream_rpc_max_wait_timeout,配置项默认值为 30s 。
但是在某些场景下还是可能出现流式 RPC 两次发送请求之间的间隔超过 30s ,因为这时接收端的工作线程已经退出里,这样就会导致流式RPC第二次发送请求的时候执行失败,返回 -4067 RPC session not found 的报错。流式 RPC 两次发送请求之间的间隔超过 30s 的典型场景:
执行 PL 语句,查询表数据时触发了远程执行计划,远程执行会发送流式 RPC,然后从流式 RPC 的回包中获取数据行,然后再对每一行执行用户写的各种 SQL/PL 语句,如果用户的 SQL 执行时间比较长,就很容易导致流式 RPC 两次发送请求超过 30s(目前线上出现的问题都是执行 PL 的时候触发的)。
执行 SQL 查询一个含有 LOB 列的数据,触发了远程执行或者是
inner sql的 RPC,因为在查 LOB 列数据的时候,每次还要再发一个 RPC,这种情况就会容易导致处理流式 RPC 结果的耗时过长超过 30s 。
问题的风险及影响
某些触发了远程执行的 SQL 会执行失败、表级恢复任务卡住。
影响租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
影响版本
OceanBase 数据库企业版 V4.2.1 GA(oceanbase-4.2.1.0-100000182023092722)及之后版本、V4.2.2 GA(oceanbase-4.2.2.0-100000082024011317)及之后版本、V4.3.0(oceanbase-4.3.0.0-100000072024020200)及之后版本。
解决方法及规避方式
解决方法:
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库 V4.2.4(oceanbase-4.2.4.0-100000252024070621)及之后版本、V4.3.1(oceanbase-4.3.1.0-100000212024051522)及之后版本。
在出现问题的租户中调大
_stream_rpc_max_wait_timeout配置项。参考事后诊断部分,从日志里找到
deliver_rpc_request和repare(ob_rpc_stream_cond.cpp:40)这两条日志,计算打印时间的差值,调大_stream_rpc_max_wait_timeout配置项比这个差值更大。 如果这个差值比较小,可以直接将_stream_rpc_max_wait_timeout设置的更大一些,如设到 2h 。_stream_rpc_max_wait_timeout配置项是租户级的,需要登陆到 SYS 租户,然后指定租户名进行设置:obclient [SYS]> alter system set _stream_rpc_max_wait_timeout = '2h' tenant '租户名';配置项修改是动态生效的,可以通过查询
GV$OB_PARAMETERS判断有没有修改成功:obclient [SYS]> select * from oceanbase.GV$OB_PARAMETERS where tenant_id = 租户 ID and name = "_stream_rpc_max_wait_timeout";
在 PL 执行报错 -4067 的场景中,SQL 执行失败的租户就是需要调整
_stream_rpc_max_wait_timeout配置项的租户,但如果遇到的是表级备份恢复卡住的问题,RPC 发送端和接收端是不同的租户。注意
修改配置项所指定的租户是日志中出现 -4208 报错所对应的租户。
规避方式:
提前调大
_stream_rpc_max_wait_timeout配置项。obclient [SYS]> alter system set _stream_rpc_max_wait_timeout = '2h' tenant '租户名';