歡迎光臨
每天分享高質量文章

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技能

贊(0)

分享創造快樂