0
0
1
0
专栏/.../

Java jdbc 驱动 maxPerformance 配置避坑

 TNTT  发表于  2024-03-21

一、现象

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=maxPerformance con.setAutoCommit(true) con2.setAutoCommit(false)
TiDB: auto commit = 0 General log 里没有 set autocommit语句(不符合代码预期) General log 里有 set autocommit=0
TiDB: auto commit = 1 General log 里没有 set autocommit语句 General log 里有 set autocommit=0
useConfigs=maxPerformance &useLocalSessionState=true con.setAutoCommit(true) con2.setAutoCommit(false)
TiDB: auto commit = 0 General log 里有 set autocommit=1 General log 里有 set autocommit=0
TiDB: auto commit = 1 General log 里有 set autocommit=1 General 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 有效

0
0
1
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论