解決方法
MySQL自身會對只讀事務做優化,這是MySQL5.6.5 版本以後纔出現的。
http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_tx_read_only
useLocalSessionState解釋及影響
1.描述
useLocalSessionState:驅動程序是否應引用autocommit的內部值,以及由Connection.setAutoCommit()和Connection.setTransactionIsolation()設置的事務隔離,而不是查詢數據庫.
2.作用
默認情況下,我們的連接串信息沒有包含useLocalSessionState參數的設置,這個值默認爲false。這個值的作用是驅動程序是否使用autocommit,read_only和transaction isolation的內部值(jdbc端的本地值)。如果設置爲false,則需要這個判斷三個參數的場景,都需要發語句到遠端請求,比如更新語句前,需要發語句select @@session.tx_read_only確認會話是否只讀。如果設置爲true,則只需要取本地值即可。這可以解釋爲什麼有的實例 select @@session.tx_read_only語句很多。一般情況下,驅動可以保證本地值與遠程服務器值保持一致。當應用調用setAutoCommit, setTransactionIsolation 和 setReadOnly這三個接口設置參數值時,會與遠程服務器同步。具體而言,當useLocalSessionState爲true時,若值與本地值不一致,則發往遠程更新。當useLocalSessionState爲false時,無論設置值與本地值是否一致,每次都發往遠程更新。這可以解釋爲什麼有些實例set autocommit語句比較多。
3.影響
但是,若用戶設置參數時不通過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語句直接設置自動提交參數,隔離級別參數或只讀事務參數。