DB大量出现select @@session.tx_read_only

在一次捞取Top SQL中,发现DB大量执行select @@session.tx_read_only,几乎每一条DML语句前,都会有这么一个sql。可是应用层并无作特殊处理,那么这个SQL语句有什么做用?是谁执行了它?html

此sql的做用主要是判断事务是否为只读事务。MySQL自身会对只读事务作优化,这是MySQL5.6.5 版本之后才出现的。http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_tx_read_onlyjava

定位到MySQL的驱动包mysql

ConnectionImpl.java :sql

能够看到,在if条件中,对MySQL的版本作了判断,同时也有  !getUseLocalSessionState()  这么一个条件,对应JDBC参数useLocalSessionState,当这个值为false时,会发出select @@session.tx_read_only; 这条sql。服务器

默认状况下,咱们的链接串信息没有包含useLocalSessionState参数的设置,这个值默认为false。
这个值的做用是驱动程序是否使用autocommit,read_only和transaction isolation的内部值(jdbc端的本地值)。
若是设置为false,则须要这个判断这三个参数的场景,都须要发语句到远端请求,好比更新语句前,
须要发语句select @@session.tx_read_only确认会话是否只读。session

若是设置为true,则只须要取本地值便可。这能够解释为何有的实例 select @@session.tx_read_only语句不少。优化

通常状况下,驱动能够保证本地值与远程服务器值保持一致。当应用调用setAutoCommit, setTransactionIsolation 和 setReadOnly这三个接口设置参数值时,会与远程服务器同步。spa

具体而言,server

当useLocalSessionState为true时,若值与本地值不一致,则发往远程更新;
当useLocalSessionState为false时,不管设置值与本地值是否一致,每次都发往远程更新。这能够解释为何有些实例set autocommit语句比较多。htm

可是,若用户设置参数时不经过JDBC接口(好比setAutoCommit),而是执行语句'set autocommit=xxx'设置,那么就会存在本地值与远程不一致的状况,进而可能致使修改参数useLocalSessionState后,业务逻辑发生变化。

相关设置的SQL语句:

     set  autocommit=0  /*设置会话自动提交模式*/                                  对应的JDBC接口:      setAutoCommit(false)

     set tx_isolation='read-committed' /*设置事务的隔离级别*/             对应的JDBC接口:setTransactionIsolation('read-committed') 

     set tx_read_only=0;  /*设置只读事务*/                                                 对应的JDBC接口:setReadOnly(false)

设置useLocalSessionState默认值为ture,可能致使业务逻辑含义发生变化。触发的条件是,用户经过SQL语句直接设置自动提交参数,隔离级别参数或只读事务参数。

相关文章
相关标签/搜索