问题现象
在 MySQL 模式下复现,示例如下。
打开黑屏窗口 1 在 mysql 租户下创建表 t1。
obclient [mysql]> create table t1(c1 varchar(755) primary key); Query OK, 0 rows affected (0.061 sec)插入数据。
obclient [mysql]> insert into t1 values('A'); Query OK, 1 row affected (0.004 sec)打开黑屏窗口 2 在 SYS 租户下执行合并。
obclient [(none)]> alter system major freeze; // 等待合并结束 Query OK, 0 rows affected (0.010 sec)第二次在已打开的黑屏窗口 1 中 mysql 租户下执行 for update 语句。
obclient [mysql]> begin; Query OK, 0 rows affected (0.000 sec) obclient [mysql]> select c1 from t1 where c1= 'a' for update; +------+ | c1 | +------+ | A | +------+ 1 row in set (0.001 sec)第二次在已打开的黑屏窗口 2 中 SYS 租户下执行合并。
obclient [(none)]> alter system minor freeze; Query OK, 0 rows affected (0.096 sec)第三次在已打开的黑屏窗口 1 中 mysql 租户下执行提交命令。
obclient [mysql]> commit; Query OK, 0 rows affected (0.002 sec)第四次在已打开的黑屏窗口 1 中 mysql 租户下执行查询。
obclient [mysql]> select * from t1; // 数据变成小写 +------+ | c1 | +------+ | a | +------+ 1 row in set (0.002 sec)
关键诊断信息
触发条件
varchar 类型的主键,之前 insert 的行中的主键与 select... for update 中主键的大小写不一致,并且过程中发生了合并转储。
问题原因
for update 做了一个 fast lock row 优化。当一个 for update 是对主键的加锁时,会使用用户的 query range 来进行加锁,从而将 rowkey 中的字符设置成用户的 for update 传入的,导致主表中的数据大小写发生变化。
发生条件: varchar 类型主键,之前 insert 的行中的主键与 select... for update 中主键的大小写不一致,并且过程中发生了合并转储,就有可能导致主表中数据大小写发生变化。
问题的风险及影响
特定场景下使用 select... for update 会导致主表中的数据大小写发生变化。
影响租户
影响 OceanBase 数据库中的 Oracle 租户和 MySQL 租户,对于 SYS 租户无影响。
影响版本
OceanBase 数据库企业版 V3.1.2 GA(oceanbase-3.1.2-20210618150922)及之后版本、V3.2.3 GA(oceanbase-3.2.3.0-20220418212020)及之后版本。
解决方法
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V3.1.2 BP10(oceanbase-3.1.2-110000022022092714)及之后版本、V3.2.3 BP6(oceanbase-3.2.3.3-106000102022111521)及之后版本。
禁止该
fast lock row优化路径。