tidb 7.5 无法转换string,行为与mysql不一致

【 TiDB 使用环境】生产环境 /测试/ Poc
【 TiDB 版本】
【复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面
【附件:截图/日志/监控】

问题简述:
tidb 7.5中,测试语句在utf8mb4字符集下执行报错,但是latin1下正常,表现与mysql/mariadb不一致,具体示例如下,请参考。

TiDB

测试用例如下,

-- tidb 7.5, utf8mb4 (default), 报错error
set names utf8mb4;
select cast(compress('b') as char);

-- tidb 7.5, latin, 正常返回
set names latin1;
select cast(compress('b') as char);

output:

MySQL [test]> select version();
+--------------------+
| version()          |
+--------------------+
| 8.0.11-TiDB-v7.5.0 |
+--------------------+
1 row in set (0.001 sec)

MySQL [test]> set names utf8mb4;
Query OK, 0 rows affected (0.000 sec)

MySQL [test]> select cast(compress('b') as char);
ERROR 3854 (HY000): Cannot convert string '
MySQL [test]> set names latin1;
Query OK, 0 rows affected (0.000 sec)

MySQL [test]> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒J  ▒▒ c c              |
+-----------------------------+
1 row in set (0.001 sec)

MySQL

对比mysql,8.2/8.0 表现一致,该语句均可返回结果,只是在utf8mb4下返回null和warn,而不是error。
MySQL 5.7 中,utf8mb4/latin 均可正常返回结果。

  • 8
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.32    |
+-----------+
1 row in set (0.00 sec)

mysql> set names utf8mb4;
Query OK, 0 rows affected (0.00 sec)

mysql> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
| NULL                        |
+-----------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+--------------------------------------------+
| Level   | Code | Message                                    |
+---------+------+--------------------------------------------+
| Warning | 1300 | Invalid utf8mb4 character string: '9C4B02' |
+---------+------+--------------------------------------------+
1 row in set (0.00 sec)

mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒K  c c               |
+-----------------------------+
1 row in set (0.00 sec)
  • 5.7
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.38    |
+-----------+
1 row in set (0.00 sec)

mysql> set names utf8mb4;
Query OK, 0 rows affected (0.00 sec)

mysql> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒K  c c               |
+-----------------------------+
1 row in set (0.00 sec)

mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒K  c c               |
+-----------------------------+
1 row in set (0.00 sec)

MariaDB

在mariadb中,utf8mb4/latin返回结果一致,

MariaDB [(none)]> set names utf8mb4;
Query OK, 0 rows affected (0.002 sec)

MariaDB [(none)]> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x?K  c c               |
+-----------------------------+
1 row in set, 1 warning (0.369 sec)

MariaDB [(none)]> show warnings;
+---------+------+-------------------------------------------------------------+
| Level   | Code | Message                                                     |
+---------+------+-------------------------------------------------------------+
| Warning | 1300 | Invalid utf8mb4 character string: '\x9CK\x02\x00\x00c\x00c' |
+---------+------+-------------------------------------------------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> set names latin1;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒K  c c               |
+-----------------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select version();
+-------------------------------------+
| version()                           |
+-------------------------------------+
| 10.7.3-MariaDB-1:10.7.3+maria~focal |
+-------------------------------------+
1 row in set (0.000 sec)
1 个赞

这应该是mysql的问题吧 8.0的时候COMPRESS函数返回的是带压缩的字符串无法转换成char,mysql8.2版本是不是偷偷改了。

5.7/8.0测试结果同上,

mysql> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒K  c c               |
+-----------------------------+
1 row in set (0.02 sec)

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.32    |
+-----------+
1 row in set (0.00 sec)


mysql> select cast(compress('b') as char);
+-----------------------------+
| cast(compress('b') as char) |
+-----------------------------+
|    x▒K  c c                |
+-----------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.7.31-log |
+------------+
1 row in set (0.00 sec)

还真是的,我试了下mysql 5.7正常的。tidb就报错。

这是版本支持问题,新版本支持,老版本不支持

测了下,tidb在报错

1 个赞

确实tidb版本都报错,mysql5.7到8都能返回

1 个赞

report issue:
https://github.com/pingcap/tidb/issues/50295

感谢文俊大佬的解答。

这个 ‘能返回’ 也没什么意义啊,本身 Comparess 得到的结果就是非法的 UTF8 编码,只不过 MySQL 报了 warning,TiDB 报了 error。

您好,感谢您的答复。

error/warn是两个告警级别了,catch的方式就会不同,相当于tidb多了一个不兼容mysql的地方。

好像以前也看别人提过类似的问题

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。