當前位置:
首頁 > 知識 > DB 大量出現 select @@session.tx_read_only

DB 大量出現 select @@session.tx_read_only

(點擊

上方公眾號

,可快速關注)




來源:Hosee ,


my.oschina.net/hosee/blog/1797234




在一次撈取Top SQL中,發現DB大量執行select @@session.tx_read_only,幾乎每一條DML語句前,都會有這麼一個sql。但是應用層並沒有做特殊處理,那麼這個SQL語句有什麼作用?是誰執行了它?




此sql的作用主要是判斷事務是否為只讀事務。MySQL自身會對只讀事務做優化,這是MySQL5.6.5 版本以後才出現的。




http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_tx_read_only




定位到MySQL的驅動包




ConnectionImpl.java :






可以看到,在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確認會話是否只讀。



如果設置為true,則只需要取本地值即可。這可以解釋為什麼有的實例 select @@session.tx_read_only語句很多。




一般情況下,驅動可以保證本地值與遠程伺服器值保持一致。當應用調用setAutoCommit, setTransactionIsolation 和 setReadOnly這三個介面設置參數值時,會與遠程伺服器同步。




具體而言,




當useLocalSessionState為true時,若值與本地值不一致,則發往遠程更新;


當useLocalSessionState為false時,無論設置值與本地值是否一致,每次都發往遠程更新。這可以解釋為什麼有些實例set autocommit語句比較多。



但是,若用戶設置參數時不通過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語句直接設置自動提交參數,隔離級別參數或只讀事務參數。




看完本文有收穫?請轉發分享給更多人

關注「ImportNew」,提升Java技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportNew 的精彩文章:

構造模式實踐
通向架構師的道路(第二十六天)漫談架構與設計文檔的寫作技巧

TAG:ImportNew |