使用DTS工具从MySQL同步到TiDB,json类型字段里面顺序错乱,导致数据校验不一致

【 TiDB 使用环境】生产环境 /测试/ Poc
【 TiDB 版本】8.1
【复现路径】使用阿里云DTS工具将mysql同步到tidb后,发现数据校验不通过。发现不一致的都是json类型的字段,比如mysql侧的数据是{“c”: xxx, “b”: xxx, “d”: xxx, “a”:xxx},但是同步到tidb后变成{“a”:xx,“b”:xx,“c”:xx,“d”:xx},这是为何原因?

感觉是同步工具 对json字段进行排序了。然后同步到tidb。

1 个赞

你找一条记录手动插入TiDB,json字段还是会变吗

测试直接写入tidb,顺序是变了,问题应该是出在tidb上

能不能从源端转成字符串,到目的端了再还原成json,这样格式和顺序就不会丢失了

测试如下:
mysql:

mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 38
Server version: 8.0.35 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

(root@10.110.66.172) [(none)]>use test
(root@10.110.66.172) [(none)]>use test;
Database changed
(root@10.110.66.172) [test]>CREATE TABLE a (
    ->     id INT AUTO_INCREMENT PRIMARY KEY,
    ->     data JSON
    -> );
Query OK, 0 rows affected (0.05 sec)

(root@10.110.66.172) [test]>INSERT INTO a (data)
    -> VALUES ('{"name": "小明", "age": 30, "city": "北京"}');
Query OK, 1 row affected (0.01 sec)

(root@10.110.66.172) [test]>select * from a;
+----+-------------------------------------------------+
| id | data                                            |
+----+-------------------------------------------------+
|  1 | {"age": 30, "city": "北京", "name": "小明"}     |
+----+-------------------------------------------------+
1 row in set (0.00 sec)

tidb:

(root@10.102.58.180) [(none)]>use test;
Database changed
(root@10.102.58.180) [test]>CREATE TABLE a (
    ->     id INT AUTO_INCREMENT PRIMARY KEY,
    ->     data JSON
    -> );
Query OK, 0 rows affected (0.14 sec)

(root@10.102.58.180) [test]>INSERT INTO a (data)
    -> VALUES ('{"name": "小明", "age": 30, "city": "北京"}');
Query OK, 1 row affected (0.01 sec)

(root@10.102.58.180) [test]>select * form a;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 13 near "form a"
(root@10.102.58.180) [test]>select * from a;
+----+-------------------------------------------------+
| id | data                                            |
+----+-------------------------------------------------+
|  1 | {"age": 30, "city": "北京", "name": "小明"}     |
+----+-------------------------------------------------+
1 row in set (0.00 sec)

所以行为是一致的。而且对于 json 格式来说,展示上的顺序我理解没啥关系,内容一样的 :thinking:

感谢回复。
我刚才那您的例子试了一下,确实mysql和tidb两边的顺序是一致的,但是我又模拟一条新数据
insert into test1(json_info) values(‘{“cccc”: 111, “aaaaa”: 30, “ddd”: “北京”}’);

mysql侧:

tidb侧:

顺序还是乱掉了

排序了应该是

JSON标准中,键值对本身是无序的吧,只是在用数据库工具查看的时候看似有顺序。
应该可以让应用在读取数据时用fastjson来做序列化的处理。

排序了但是理论来说json取数不也是kv影响大吗

你这写入顺序和 MySQL 展示顺序不也不一样。

本身就不保证顺序的,不然你就按照数组存。如果需要顺序。https://dev.mysql.com/doc/refman/8.0/en/json.html

1 个赞