【五一创作】【Mycat】Mycat2 Bugs 及修改建议(V1.22_2022-10-13)

文章详细列举了Mycat2在配置、SQL解析和用户权限方面遇到的多个Bug,包括数字类型参数配置错误、SQL语义验证缺失、逻辑库名与物理库名混淆、JSON文件名与配置不一致、原型库引起的混淆和冲突、逻辑表与物理表命名差异以及用户配置中IP识别问题。建议改进配置规范和SQL解析机制,以提高用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bug 1 : wrapper.conf 数字类型参数配置有误,多了末尾的单位 M

在这里插入图片描述

https://wrapper.tanukisoftware.com/doc/english/prop-java-initmemory.html

wrapper.log 产生警告:

WARN   | wrapper  | 2023/04/20 22:42:00 | Encountered an invalid numerical value for configuration property wrapper.java.initmemory=256M.  Resolving to 256.
WARN   | wrapper  | 2023/04/20 22:42:00 | Encountered an invalid numerical value for configuration property wrapper.java.maxmemory=2048M.  Resolving to 2048.

Bug 2 : 执行错误的指令也不会报错

在 Mycat2 终端中执行任一满足 SQL 语法规则的 SQL 语句均不会报错,Mycat2 似乎不会去做语义分析验证对象的有效性。

例如,笔者并没有创建 ttt 数据库,但却可以 use ttt 且不报错。

mysql> use ttt;
Database changed
mysql> show tables;
Empty set (0.05 sec)

mysql> show databases;
+--------------------+
| `Database`         |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| testdb             |
+--------------------+
4 rows in set (0.00 sec)

Bug 3 : 逻辑库名错误识别为物理库名

最初,我认为 schemaName 是指逻辑库(方案)名,测试发现 Mycat 启动时报错,但最后却启动成功了。问了 Mycat 社区 并没有解决。

在这里插入图片描述

后来我将其配置为逻辑库对应的物理库名,启动时就不报错了。这让我认为 schemaName 是指物理库名。

再后来,当我发现 Bug 5 时,确信了 schemaName 是指逻辑库名,只是当前版本的 Mycat2 解析器有问题,要求原型库或数据源中必须存在与该逻辑库同名的物理库

另外,当配置的逻辑库名与实际物理库名相同时,Mycat2 会自动获取表信息;否则不会自动获取表信息,需要为每一个逻辑表配置映射关系。

[root@ic-source conf]$ cat schemas/mycat_db.schema.json 
{
        "customTables": {},
        "globalTables": {},
        "normalTables": {
                "logical_t1": {
                        "createTableSQL":"CREATE TABLE `logical_t1` (\n  `id` int DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci",       // 可选
                        "locality": {
                                "schemaName": "testdb", // 物理库,可选
                                "tableName": "t1",      // 物理表,可选
                                "targetName": "cls02"   // 指向集群,或者数据源
                        }
                }
        },
        "name": "mycat_db",     // Mycat2 暂不支持
        "schemaName": "mycat_db",
        "shardingTables": {},
        "targetName": "cls02"
}

当我将最外层的 schemaName 设置为 mycat_db 时,除了显式配置逻辑表 t2 ,无论怎么配置,Mycat2 都不会获取到 testdb.t2 表的信息。

在这里插入图片描述

[root@ic-source conf]$ cat schemas/mycat_db.schema.json
{
        "customTables": {},
        "globalTables": {},
        "normalTables": {
                "logical_t1": {
                        "createTableSQL": null, // 可选
                        "locality": {
                                "schemaName": "testdb", // 物理库,可选
                                "tableName": "t1",      // 物理表,可选
                                "targetName": "cls02"   // 指向集群,或者数据源
                        }
                },
                "logical_t2": {
                        "locality": {
                                "schemaName": "testdb", // 物理库,可选
                                "tableName": "t2",      // 物理表,可选
                                "targetName": "cls02"   // 指向集群,或者数据源
                        }
                }
        },
        "name": "mycat_db",     // Mycat2 暂不支持
        "schemaName": "mycat_db",
        "shardingTables": {},
        "targetName": "cls02"
}

在这里插入图片描述

不支持自动获取逻辑库中未配置而在物理库中存在的表,例如 testdb.t2

在这里插入图片描述

下图是我为了说明问题伪造的。
在这里插入图片描述

不知 Mycat2 是这块具体怎么实现的。

修改建议

  • schemaName 改名为 namelogicalSchemaName 属性以作区分,避免逻辑库名与物理库名混淆不清。而且,没必要要求必须存在与逻辑库同名的物理库。
  • 增加三个属性:一个 defaultLocality 属性,包含两个子属性: defaultSchemaNamedefaultTargetName 。它们用于当没有为逻辑表配置 locality 属性时,为其指定默认的映射关系。
  • 支持动态调整 Schema 配置文件,而不是每次修改都要重启。Schema 级别应该设计得与 集群数据源 级别不同,支持动态调整。最好全都支持动态调整,毕竟 Mycat 整体是个逻辑结构。

Bug 4 : 无法识别JSON 文件名中的逻辑库名称,且配置文件内缺少相应属性

Mycat2 服务启动没有任何报错。

在这里插入图片描述

$MYCAT_BASE/conf/schemas/mycat_db.schema.json 如下,其中 $MYCAT_BASE 为 Mycat2 的安装目录:

[root@ic-source conf]$ cat schemas/mycat_db.schema.json 
{
        "customTables": {},
        "globalTables": {},
        "normalTables": {
                "logical_t1": {
                        "createTableSQL":"CREATE TABLE `logical_t1` (\n  `id` int DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci",       // 可选
                        "locality": {
                                "schemaName": "testdb", // 物理库,可选
                                "tableName": "t1",      // 物理表,可选
                                "targetName": "cls02"   // 指向集群,或者数据源
                        }
                }
        },
        "schemaName": "testdb",	//物理库名,而非逻辑库名
        "shardingTables": {},
        "targetName": "cls02"
}

可以看到,该 JSON 配置文件名中的“方案名”为 mycat_db ,而在配置文件内容中却并没有相应的配置,其中的 schemaName 经测试是指物理库名。建议新增一个属性 namelogicalSchemaName 表示逻辑库名,与 clusters/prototype.cluster.jsondatasources/prototypeDs.datasource.json 的配置规则(配置文件内包含 name 属性,与 JSON 文件名称一致)保持一致。

clusters/prototype.cluster.json 内容如下:

在这里插入图片描述

datasources/prototypeDs.datasource.json 内容如下:

在这里插入图片描述

而目前即便我配置了 `name· 属性,Mycat2 当前版本仍无法识别。

在这里插入图片描述

登录 Mycat2 终端,查看逻辑库名仍为物理库名 testdb ,期望为 mycat_db

在这里插入图片描述

所以,当前版本应将 JSON 文件名称中的“方案名”(即“数据库名”)设置为与数据源的实际物理库中的“方案名”相同,因为即便你配置得不同,Mycat2 也不识别。

  • 如果采用某个读写数据源指向的物理库作为原型库,应该会报错,这个笔者以后有时间测试后补上。

  • 如果未配置原型库,则在 Mycat2 终端中创建的所有数据库及内部对象只是 JSON 文件及其内容。

Bug 5 : 使用独立的原型库时造成混淆和冲突报错

此外,当配置一个独立的原型库时,会造成混淆。因为即便存在物理库 testdb ,仍可创建新的 testdb(实际创建在独立的原型库中)造成混淆。

测试过程如下:

  1. 在 Mycat2 独立的原型库使用 MySQL 终端 mysql 查看:
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mycat              |
    | mysql              |
    | performance_schema |
    | sys                |
    +--------------------+
    5 rows in set (0.01 sec)
    
  2. Mycat2 终端 执行:
    mysql> create database testdb;
    Query OK, 0 rows affected (0.78 sec)
    
    mysql> show databases;
    +--------------------+
    | `Database`         |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | testdb             |
    +--------------------+
    4 rows in set (0.08 sec)
    
    mysql> show tables from testdb;
    +------------------+
    | Tables_in_testdb |
    +------------------+
    | logical_t1       |
    | t1               |
    | t2               |
    +------------------+
    3 rows in set (0.05 sec)
    
  3. 在 Mycat2 独立的原型库使用 MySQL 终端 mysql 查看:
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mycat              |
    | mysql              |
    | performance_schema |
    | sys                |
    | testdb             |
    +--------------------+
    6 rows in set (0.00 sec)
    
    可以看到,在原型库中创建了 testdb 数据库。
    此操作还会再 Mycat2 服务器上的 conf/schemas 目录下产生 testdb 的配置文件:
    [root@ic-source conf]$ ll schemas/
    总用量 24
    -rw-r--r--. 1 root root 2463 421 15:49 information_schema.schema.json
    -rw-r--r--. 1 root root  529 429 21:29 mycat_db.schema.json
    -rw-r--r--. 1 root root 3984 422 19:26 mycat.schema.json
    -rw-r--r--. 1 root root 5299 421 15:49 mysql.schema.json
    -rw-r--r--. 1 root root  962 429 21:53 testdb.schema.json
    [root@ic-source conf]$ cat schemas/testdb.schema.json 
    {
            "customTables":{},
            "globalTables":{},
            "normalProcedures":{},
            "normalTables":{
                    "logical_t1":{
                            "createTableSQL":"CREATE TABLE `logical_t1` (\n  `id` int DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci",
                            "locality":{
                                    "schemaName":"testdb",
                                    "tableName":"t1",
                                    "targetName":"cls02"
                            }
                    },
                    "t1":{
                            "createTableSQL":"CREATE TABLE `testdb`.`t1` (\n\t`id` int DEFAULT NULL\n) ENGINE = InnoDB CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci",
                            "locality":{
                                    "schemaName":"testdb",
                                    "tableName":"t1",
                                    "targetName":"cls02"
                            }
                    },
                    "t2":{
                            "createTableSQL":"CREATE TABLE `testdb`.`t2` (\n\t`id` int NOT NULL,\n\t`name` varchar(30) NOT NULL,\n\tPRIMARY KEY (`id`)\n) ENGINE = InnoDB CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci",
                            "locality":{
                                    "schemaName":"testdb",
                                    "tableName":"t2",
                                    "targetName":"cls02"
                            }
                    }
            },
            "schemaName":"testdb",
            "shardingTables":{},
            "views":{}
    }
    
    这俩配置文件内容几乎一样,会在重启 Mycat 时因冲突报错。
    在这里插入图片描述

重启 Mycat2 时会失败,报错:
在这里插入图片描述
修改 Mycat2 自动生成的 schemas/testdb.schema.json 配置后,内容如下:

[root@ic-source conf]$ cat schemas/testdb.schema.json
{
        "customTables":{},
        "globalTables":{},
        "normalProcedures":{},
        "normalTables":{},
        "schemaName":"testdb",
        "shardingTables":{},
        "views":{},
        "targetName":"prototype"
}

重启 Mycat2 仍然报错。

在这里插入图片描述

此时,证实了 schemaName 属性实际上就是我所说的 namelogicalSchemaName 。兜兜转转,证明还是 Mycat2 SQL 解析器的问题。我认为此处不应该报错产生 [Error] 日志,而应产生 [INFO][WARN] 日志,提醒用户这么配置将导致逻辑库与物理库名称不一致。

Bug 6 : 逻辑表与物理表非同名时会看到“幻象”

使用上面 Bug 4 中的 $MYCAT_BASE/conf/schemas/mycat_db.schema.json 配置。

在这里插入图片描述

Mycat2 终端 查看:

在这里插入图片描述

MySQL 终端 查看:

在这里插入图片描述

Bug 7 : Mycat2 用户配置中 IP 无法识别 DNS 和主机名

users/root.user.json 文件内容如下:

[root@ic-source conf]$ cat users/root.user.json 
{
        "dialect":"mysql",      // SQL 方言
        "ip":null,
        "username":"root",      // Mycat 用户名
        "password":"123456",    // 上面的 Mycat 用户名的密码
        "transactionType":"proxy",
}

当笔者将 ip 属性限制为只有 IP 地址192.168.52.6主机名replica3 主机能访问时,分别使用 IP 地址和主机名却产生了不同的结果。

以下为 /etc/hosts 部分内容:

[root@ic-source ~]$ cat /etc/hosts
192.168.52.6 replica3

设置为 IP 地址或网段

修改 users/root.user.json 文件内容:

"ip":192.168.52.,

重启 Mycat 。

在非 replica3 主机上连接 Mycat2 报错:
在这里插入图片描述

replica3 主机上连接 Mycat2 成功:
在这里插入图片描述

配置为 IP 网段时 Mycat2 也可以识别。此处不加赘述。

设置为主机名

修改 users/root.user.json 文件内容:

"ip":"replica3",

重启 Mycat 。

replica3 主机上连接 Mycat2 报错:
在这里插入图片描述


笔者认为 Mycat2 的原型库设计有问题,只需要设计为元数据库即可。而开发者还试图将其作为处理数据库管理语句、DDL 语句等 SQL 语句的默认数据库。所有 MySQL 分库分表中间件的最终目的都是构建一个完整的 SQL 解析器,既要解析中间件自定义的语法,又要解析 MySQL 不断更新的所有语法,无疑会带来很高的实现复杂度。Mycat2 则选择了一种折中的办法,将无法解析处理的 SQL 在原型库上执行,以提高业务连续性,但他们没有考虑到用户很少使用、甚至不要该功能。在底层为复制拓扑,Mycat2 原型库为复制拓扑的 (复制)源(Source/Master) 时,还算有点用处。

首先,使用数据库中间件是需要一定的学习成本的,尤其是涉及到复杂的分库分表规则时。

其次使用 Mycat 中间件的用户,主要需求就是分库分表、分布式事务,对于 DDL、数据库管理语句等,基本不会在 Mycat 上操作。

最后,当前的原型库设计即便运行了DDL、数据库管理语句这些无法解析的语句,但却违背了用户本意,实属无用功,用户还要去处理 Mycat 因误解而带来的后果,比如删除在原型库中创建的数据库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独上西楼影三人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值