Java jdbc 驱动 maxPerformance 配置避坑的方法

Tiit 544 2024-03-25

一、现象

https://docs.pingcap.com/zh/TiDB/stable/performance-tuning-practices#%E5%BA%94%E7%94%A8%E9%85%8D%E7%BD%AE-1

官方文档建议使用 maxPerformance 屏蔽 JDBC 向数据库发送的一些查询设置类的 SQL 语句

发现使用 maxperformance 后,数据库事务行为和预想的不一致。

具体情况如下

useConfigs=maxPerformancecon.setAutoCommit(true)con2.setAutoCommit(false)
TiDB: auto commit = 0General log 里没有 set autocommit语句(不符合代码预期)General log 里有 set autocommit=0
TiDB: auto commit = 1General log 里没有 set autocommit语句General log 里有 set autocommit=0
useConfigs=maxPerformance &useLocalSessionState=truecon.setAutoCommit(true)con2.setAutoCommit(false)
TiDB: auto commit = 0General log 里有 set autocommit=1General log 里有 set autocommit=0
TiDB: auto commit = 1General log 里有 set autocommit=1General log 里有 set autocommit=0

二、排查

useConfigs = maxPerformance 在 Mysql-connector 等同于如下的一组配置

cachePrepStmts=true
cacheCallableStmts=true
cacheServerConfiguration=true
useLocalSessionState=true
elideSetAutoCommits=true
alwaysSendSetIsolation=false
enableQueryTimeouts=false
connectionAttributes=none

其中 jdbc 驱动是依赖 useLocalSessionState 这个变量,来决定是使用数据库本身的 auto commit状态还是直接根据 java 的配置直接发送事务配置命令给数据库

Should the driver refer to the internal values of auto-commit and 
transaction isolation that are set by 'Connection.setAutoCommit()' 
and 'Connection.setTransactionIsolation()' and 
transaction state as maintained by the protocol,
rather than querying the database or blindly sending commands 
to the database for 'commit()' or 'rollback()' method calls?

再根据 jdbc 驱动源码验证

Jdbc 创建连接的时候会去看 tidb 里的 autocommit 和 init_connect 的值,但看起来不论如何,都会给 jdbc 内部的 autocommit 变量设置为 true。即 tidb 里的 autocommit 不论设成什么,jdbc 都认为是 true。

Jdbc 通过 uselocalseesionstate、autocommit == autocommitflag 判断是否该发 autocommit 给服务器。

从代码逻辑来看:

  1. 当 tidb 为 true,jdbc 为 true 时,不重新设置事务状态

  2. 当 tidb 为 true,jdbc 为 false,显示设置会话事务状态

  3. 当 tidb 为 false,jdbc 为 true,不重新设置会话事务状态

  4. 当 tidb 为 false,jdbc 为 false,显示设置会话事务状态

三、结论

当使用useConfigs = maxPerformance 时候,如果关闭 TiDB 数据库层面的 auto commit,同时代码里 con.setAtuCommit(true) 会导致这部分事务一直不提交,数据写入不成功,需要通过在 jdbc 里使用useLocalSessionState=true 来解决

useConfigs = maxPerformance

TiDB autocommit 1

TiDB autocommit 0

Java setautocommit(true)

Java 有效

Java 无效(不符合代码预期)

Java setautocommit(false)

Java 有效

Java 有效


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:解读TiKV 状态变化
下一篇:探讨TiDB 三中心"脑裂"场景
相关文章