序:在项目工作中需要从三方厂商数据库同步数据到项目业务库中,本平平无奇的功能却被一个报错打破。

  在使用某框架的DataSourceConfig(Object)方法初始化数据库连接时,日志输出报错:

    Unknown system variable 'transaction_isolation'

  经过网上查找相关资料,发现问题现象大同小异都是连接驱动与数据库版本不匹配。从 MySql-5.7.20 版本后 transaction_isolation 作为 tx_isolation 的别名被引入,而在mysql-8.0之后的版本tx_isolation参数被彻底废弃。给出的解决方案无非就是:1.升级数据库的版本。2.降低MySQL连接驱动的版本。

  方法1:升级数据库版本

  数据库为三方厂商的生产数据库,让他们升级数据库版本似乎不太可能。

  方法2:降低MySQL连接驱动版本

  要降低连接驱动版本,首先要确定三方厂商的数据库版本,在查询他们的数据库版本时,令人窒息的事情发生了,查询出他们的数据库版本为MySQL-5.7.99。

  What?,在MySQL-5.7.20版本后,不是已经有transaction_isolation参数了吗?而且用 show variables like 't%_isolation'; 语句在三方库查询,确实没有transaction_isolation这个系统参数。下表是使用同一语句在三方数据库库和我们数据库查询结果。

表1

 三方数据库  我方数据库
show variables like 't%_isolation';  
show variables like 't%_read_only';
select version();

  可以看到我方查询事务隔离级别的语句是包含transaction_isolation和tx_isolation系统参数,而三方库只有tx_isolation这一个。没办法只能更换驱动包试试,找到MySQL-5.7.20版本适配的驱动包版本是mysql-connector-java-5.1.12,替换系统中的jar包后重启业务应用,结果在启动过程中因为不适配低版本的驱动包导致启动报错。立即更换其他稍微高点版本的驱动,虽然启动没报错了,但是三方的数据库在连接时依然报出Unknown system variable 'transaction_isolation'这个错误。看来更换连接驱动这个办法也行不通。

  没办法只能先看看mysql-connector-java驱动的源码,看能不能从源码中找到问题。连接驱动版本为5.1.48。先从报错日志打印的错误堆栈信息入手。

图1

  好在方法调用层级不算多,众所周知java方法调用信息使用“栈”结构进行存储,栈弹出逻辑为即“先进后出”,那么最下面的方法就是要排查的起点。从ConnectionImpl.connectWithRetries()方法依次为ConnectionImpl.initializePropsFromServer()、ConnectionImpl.loadServerVariables() ...... 进行查看。

  首先看 ConnectionImpl.connectWithRetries()方法,此方法做了些参数初始化后调用了initializePropsFromServer()方法:

图2

 在initializePropsFromServer()方法中也是初始化参数后调用了loadServerVariables()方法,进入到loadServerVariables()方法后发现了问题的关键。

图3

其中有行判断数据库版本后,选择在查询系统参数的sql中拼接 @@tx_isolation AS transaction_isolation 还是拼接 @@transaction_isolation AS transaction_isolation语句,而三方库数据库版本为MySQL-5.7.99,不满足条件则拼接的查询语句为 @@transaction_isolation AS transaction_isolation 从而引起报错。查看连接驱动版本大于5.1.48的的源码判断逻辑也是如此,那么就排除是连接驱动jar包bug的问题。可以确定问题就出在了这个不按常理出牌的三方数据库身上。当时正值深夜,而且三方数据库已投入生产使用,也不可能让厂商处理数据库问题,那么就只能看看能不能修改源码规避掉这个问题。

图4 在三方数据库执行查询语句

我方数据库版本也是使用transaction_isolation参数来查询事务隔离级别,但是通过前期的排查,发现同时存在tx_isolation这个系统参数(详见表1)。那么把queryBuf.append(", @@transaction_isolation AS transaction_isolation"); 改为 queryBuf.append(", @@tx_isolation AS transaction_isolation");,不仅可以规避掉三方数据库没有transaction_isolation参数的问题,而且也不会对我们的数据库造成影响。只需要下载源码修改后再编译为jar包就可以了。

  从github(https://github.com/mysql/mysql-connector-j/blob/5.1.48/src)上找到5.1.48版本的源码后导入工程,修改完成后发现并不能直接编译,因为还引用了hibernate,而源码中也没找到关于其他依赖引用的描述,依赖问题一时半会也解决不了,那么就直接修改编译后的class字节码文件吧。

把mysql-connector-java-5.1.48.jar中的ConnectionImpl.class文件提取出来,使用jclasslib工具打开,在“方法”中搜索 loadServerVariables,在字节码文件中找到拼接“, @@transaction_isolation AS transaction_isolation”对于的行,点击行中间的常量地址跳转到常量池,在常量池把值修改为“, @@tx_isolation AS  transaction_isolation”后保存,把修改后文件放回jar包中。

  

图5

  jar包调整完成后更新应用,发现连接三方库还是有报错,但从这次的异常日志中发现报错的方法变了,原来在getTransactionIsolation()方法中也需要把transaction_isolation改为tx_isolation。还是用上面的方法修改后再更新应用。

图6

  再次更新后发现又报Unknown system variable 'transaction_read_only'的错误,看来之前的修改是有效果的。transaction_read_only和transaction_isolation一样,都是在MySQL-5.7.20版本后加进去的,而三方数据库只有tx_read_only这个系统参数,我们的数据库既有transaction_read_only又有tx_read_only,还是可以使用上面的方法进行调整。根据报错调整isReadOnly()方法,调整完成更新后,再次连接三方数据库,可正常连接,同时业务应用没有因为驱动调整而产生报错和异常。

图7

事后在MySQL官网查询,并没有发现又5.7.99的版本,那么友商5.7.99这个版本的数据库到底从何而来?为何数据库会缺少系统参数?至今仍是个迷......

图8

完......

MySQL版本5.7.99?相关推荐

  1. 查看mysql版本的四种方法

    2019独角兽企业重金招聘Python工程师标准>>> 查看mysql版本的四种方法 1:在终端下:mysql -V. 以下是代码片段: [shengting@login ~]$ m ...

  2. mysql版本 时间_【MySQL】MySQL版本时间线和MySQL各版本的区别

    MySQL各版本的区别 https://yq.aliyun.com/articles/607474 http://blog.sina.com.cn/s/blog_62b37bfe0101he5t.ht ...

  3. php mysql切换版本5.7_phpstudy 升级 MySQL版本到MySQL5.7

    #### 起因:我用laravel6做迁移的时候,总是报这个错误 SQLSTATE[42000]: Syntax error or access violation: 1071 Specified k ...

  4. MYSQL.版本查看-LINUX

    MYSQL.版本查看-LINUX 方式1: 不需登录mysql,登录Linux服务后,执行如下指令: # mysql -V 注意: 那个是大写的V,如果使用小写的v,在root没有设置密码的情况下,就 ...

  5. windows 下phpstudy 升级mysql版本5.7

    今天在导入sql文件的时候遇到了sql执行错误.最后找到原因是因为mysql版本过低,导致出错 原因:在执行sql的时候出现了两次CURRENT_TIMESTAMP ,最后得知在5.7版本之前都是不支 ...

  6. canal中mysql版本错误日志

    为什么80%的码农都做不了架构师?>>>    canal错误代码: pid:34 nid:1 exception:canal:canal-ec-to-smarti-110:com. ...

  7. mariadb mysql版本对应_弹指神通MariaDB——MariaDB与MySQL各版本的区别

    1 MariaDB的性质 MariaDB从MySQL衍生而来,作为完全开源的一款数据库产品.关于MariaDB更详细的信息其实是在MariaDB.org中.在MariaDB download中也做了详 ...

  8. flowable支持的mysql版本_Flowable3-配置

    创建一个ProcessEngine Flowable流程引擎通过名为的XML文件进行配置flowable.cfg.xml. 获得一个最简单的方法ProcessEngine是使用这个org.flowab ...

  9. linux安装指定mysql版本安装,linux yum安装指定版本mysql

    1.下载mysql rpm包 cd /usr/local/src wget https://dev.mysql.com/get/mysql80-community-release-el7-.noarc ...

最新文章

  1. [UWP小白日记-14]正则表达式
  2. python做出来的东西_【python小白】 做了一个爬虫,但是爬出来的东西无法存储...
  3. leetcode 调整数组顺序使奇数位于偶数前面
  4. 【NOIP 模拟题】[T1] 等差数列(dp)
  5. 企业云存储:为什么中大型企业偏爱自建私有云?
  6. 计算机与操作系统基础小结
  7. 面向对象编程思想-观察者模式
  8. 高位字节 低位字节_所有字节从何而来?
  9. 关于runc漏洞CVE-2019-5736的修复公告
  10. ZTree相关使用的例子
  11. c#自带压缩类实现数据库表导出到CSV压缩文件的方法
  12. 利用SQL语言修正与撤销数据库
  13. windows下使用vim
  14. 21世纪八大新兴技术领域对美国战略威慑的影响
  15. 线路,数据通路,数据总线的关系
  16. 【STM32F407的DSP教程】第1章 初学数字信号处理准备工作
  17. 天狮集团云函数实践:自定义业务逻辑实现跨境电商全球直播
  18. 使用npm下载包,报错 error An unexpected error occurred: “EPERM: operation not permitted
  19. [几何画板]正十七边形的做法
  20. oracle笔记:新手上路必备。花了两天时间整理出来的,详细的不能再详细了。

热门文章

  1. 应用TEA5767的调频收音电路设计(转)
  2. 第四十八讲 uevent
  3. 宝鲲财经炒外汇必知技巧概述
  4. Android 设置飞行模式,判断是否是飞行模式
  5. 以太坊合并四大支柱重振生态信心
  6. c语言枚举型与联合体
  7. 牛透社深访:微盛 0 到百万级的双域循环增长公式
  8. 使用webdriver+urllib爬取网页数据(模拟登陆,过验证码)
  9. 音视频直播开发问题分析总结 -- 花屏绿屏
  10. CSDN 职场论坛问答精选1