目录
一、问题现象:
1、数据库中间件
前段时间尝试在项目中使用数据库中间件(Mycat2或ShardingSphere Proxy)做数据库读写分离和分库分表的处理。
本文相关环境和程序依赖包版本: MySQL 8.0.28、Mycat 2-1.20/21、MySQL.Data 8.0.28、MySql.EntityFrameworkCore
顺利搭建配置完成Mycat2,并在数据库客户端(Navicat)中执行测试SQL正常。
满怀期待的使用程序连接Mycat2。
2、启动.net程序
(1)报错现象
(2)查看mycat日志
3、原因查看
Fatal error encountered during command execution(命令执行过程中遇到致命错误)
Fatal error encountered during command execution
难道.NET平台下又不兼容嘛!!!
网上搜了一下相关错误,有用的信息好少(.net 程序员的痛...)。
又仔细查看了InnerException
UtcTimestampFunction.utcTimestamp(java.lang.Integer)
Future{cause=Line 23, Column 229: No applicable constructor/method found for zero actual parameters; candidates are: "public static java.time.LocalDateTime io.mycat.calcite.sqlfunction.datefunction.UtcTimestampFunction.utcTimestamp(java.lang.Integer)
是执行UTC_TIMESTAMP函数错误,不支持无参数执行(参数:毫秒精度)?在数据库客户端执行试一下
UTC_TIMESTAMP()
咦,报错,在MySQL中这个函数是可以正常执行的,Mycat2不兼容无参数执行这个函数?
去官网看一下:https://www.yuque.com/ccazhw/ml3nkf/vm9gru
官网提示这个函数是兼容的,那就是BUG咯。
4、解决思路
现在怎么解决呢,又思考:程序中并没有地方用到UTC_TIMESTAMP函数,程序刚启动只执行了简单的查询操作,实现的ORM中也没有用到这个函数,去底层类库找一下,发现在MySQL.Data类库中打开数据库连接,加载服务器信息时有一个获取时区偏移量的方法(GetTimeZoneOffset)用到了UTC_TIMESTAMP函数,这下定位到问题了!!!
(MySQL.Data GetTimeZoneOffset)
另外:MySql.EntityFrameworkCore也用了MySQL.Data,因此连接使用Mycat2也会报同样的错误。如下图:
5、解决方法
1、方法一:
使用获取mycat的源码定位到报错的位置修复错误,更新jar包。
2、方法二:
使用MySqlConnector类库代替官网的MySQL.Data,很多ORM框架底层也是引用的MySqlConnector,替换也比较方便。
MySQL.Data | MySql.EntityFrameworkCore |
MySqlConnector | Pomelo.EntityFrameworkCore.MySql、SqlSugar、Dapper等 |
3、方法三:
根据前面的异常提示No applicable constructor/method found for zero actual parameters,给函数传个参数就可以正常执行。
因此可以拉取MySQL.Data类库修改获取时区偏移量(GetTimeZoneOffset)的方法
MySQL.Data GetTimeZoneOffset
4、mycat2升级只1.22可以解决:
有人说升级到1.21就已经解决了,但是我的环境就是1.21的(可能是小版本不同),并未解决,1.22确实是修复了。
采取哪种方法解决此问题根据项目情况而定,最后我们还是希望Mycat尽快修复此BUG,也感谢马老板为我们提供了很多好用的开源中间件。