问题现象
客户端新老版本混跑场景,OBServer 端 prepare 阶段跟 execute 阶段返回的列数量不一致,导致客户端校验报错。
问题原因
背景
- 业务老进程使用了 OBCI V1.x 版本,该版本并不支持处理 ROWID,在建立连接的时候并不会带上
OB_CLIENT_RETURN_HIDDEN_ROWIDflag。 - 业务新进程使用了 OBCI V2.0.1.x 版本,该版本支持处理 ROWID,在建立连接的时候会带上
OB_CLIENT_RETURN_HIDDEN_ROWIDflag。 - OBServer 根据客户端建连时是否带上
OB_CLIENT_RETURN_HIDDEN_ROWIDflag 来判断是否需要返回 ROWID。
问题场景
- 业务一开始使用了 OBCI V1.x 版本进行 prepare,因为该版本在建连的时候并不会带上
OB_CLIENT_RETURN_HIDDEN_ROWIDflag,所以 OBServer 返回的列中也不包含 ROWID。并且 OBServer 端会对该 prepare 语句以及返回的列进行 cache(缓存在 ps cache 中)。 - 业务一开始同样使用了 OBCI V1.x 版本进行 execute,因为该版本在建连的时候并不会带上
OB_CLIENT_RETURN_HIDDEN_ROWIDflag,所以 OBServer 返回的列中也不包含 ROWID。并且 OBServer 端会把该语句生成的物理计划进行 cache(缓存在plan cache中)。 - 当业务使用 OBCI V2.0.1.x 版本进行 prepare、execute 时也会命中用 OBCI V1.x 版本生成的 ps cache 跟 plan cache。此时因为缓存的信息都是用 OBCI V1.x 版本生成的(即都不带 ROWID)所以不会有问题。
- 合并之后会淘汰以前的 plan cache 重新生成执行计划,此时当业务使用 OBCI V2.0.1.x 版本进行 prepare、execute 时会命中 OBCI V1.x 版本 prepare 生成的信息(即不包含ROWID列信息),但是因为物理计划被淘汰掉会重新用 OBCI V2.0.1.x 版本生成物理执行计划,此时会返回 ROWID 信息,导致 prepare 阶段跟 execute 阶段返回的列数量不一致报错。
问题的风险及影响
客户端校验报错。
影响版本
OceanBase 数据库企业版 V2.2.77 BP19、V3.1.2 BP12、V3.2.3 BP11、V3.2.4 BP7(oceanbase-3.2.4.7-107000012023113010)、V4.1.0 BP5、V4.2.1 BP2(oceanbase-4.2.1.2-102010012023120119) 之前的所有版本。 OceanBase 数据库社区版 V3.1.5-CE(oceanbase-ce-3.1.5-100000252023041721) 之前的所有版本。
解决方法及规避方式
- 客户端使用同一个版本,然后执行
alter system flush ps cache; alter system flush plan cache;可以规避。 - 升级到问题已修复版本,目前已修复的版本包含 V4.2.1 BP2(oceanbase-4.2.1.2-102010012023120119)、V3.1.5-CE(oceanbase-ce-3.1.5-100000252023041721) 及之后版本。