MySQL案例:关于JSON的一个bug

时间:2022-07-24
本文章向大家介绍MySQL案例:关于JSON的一个bug,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言

周五晚上和朋友一起去外面吃饭,本来想着不加班早点回家过周末,谁又能想到突然就接到一个电话,mysqldump逻辑备份导入时报错,具体错误为“ERROR 3144 (22032): Cannot create a JSON value from a string with CHARACTER SET 'binary'.”

下面就和大家简单分享一下这个案例,由于涉及业务数据,这里将通过自己模拟场景的方式来进行分享;关于真实场景或模拟场景分享,之前也说过,能够自己模拟复现出故障场景,往往才更加证明已经完全了解清楚其中的原理和解决办法。

案例分享

(1)创建一张含JSON列的表,并插入一条记录

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

mysql> show create table json_testG
*************************** 1. row ***************************
       Table: json_test
Create Table: CREATE TABLE `json_test` (
  `id` int NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  `a` json DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql> insert into json_test(id,name,a) values(1,'1','{"id":"1","name":"1"}');
Query OK, 1 row affected (0.01 sec)

(2)通过mysqldump导出该表

$ mysqldump -uroot -p --set-gtid-purged=off test json_test > json_test.sql

(3)尝试导入数据,报错如下,看起来似乎是与字符集有关

mysql> source json_test.sql
...
ERROR 3144 (22032): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
...

(4)查看该SQL文件,发现里面 /*!50503 SET NAMES binary */; 这条SQL比较可疑,和报错相关

(5)进一步查阅文档,发现与官方两个bug相关,Bug #86709和Bug #88288

Bug #86709:https://bugs.mysql.com/bug.php?id=86709
Bug #88288:https://bugs.mysql.com/bug.php?id=88288

(6)尝试修改SQL文件,将 /*!50503 SET NAMES binary */; 改为 /*!50503 SET NAMES utf8mb4 */; 并导入成功,问题解决

mysql> source /tmp/backup/cdb-dki7pq4r_backup_20200828202032.sql
...
Query OK, 1 row affected (0.01 sec)
...

mysql> select * from json_test;
+----+------+--------------------------+
| id | name | a                        |
+----+------+--------------------------+
|  1 | 1    | {"id": "1", "name": "1"} |
+----+------+--------------------------+
1 row in set (0.00 sec)

总结

关于这个问题,我们可以通过修改SQL文件中的字符集解决;后续我也对MySQL新版本(5.7.30和8.0.20),进行了测试,已经修复该bug。