MySQL JDBC 出現多個 SHOW VARIABLES 語句。

流水無情88發表於2016-11-22

一次偶然的機會,show processlist 的時候,發現有個 Client 一直在執行  "mysql-connector-java-5.1.21 ( Revision: ${bzr.revision-id} ) */SHOW VARIABLES WHERE Variable_name"

後面和基友一起討論,稍微縷了一下。大概思路是這樣的的:

 

1.MySQL JDBC 連線過程大概如下(開啟 general log 獲得的資訊):

5089492 Connect user@ip on db
                5089492 Query   /* mysql-connector-java-5.1.21 ( Revision: ${bzr.revision-id} ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'init_connect'
                5089492 Query   /* mysql-connector-java-5.1.21 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increment_increment
                5089492 Query   SHOW COLLATION
                5089492 Query   SET NAMES utf8mb4
                5089492 Query   SET character_set_results = NULL
                5089492 Query   SET autocommit=1
                5089492 Query   SET sql_mode='STRICT_TRANS_TABLES'

  1)Connect user@ip on db

  2)SHOW VARIABLES WHERE Variable_name ='language'... 獲取 Client 關心的 session 級別變數。

  3)獲取 @@session.auto_increment_increment . 這個引數的作用請參考 https://dev.mysql.com/doc/refman/5.5/en/replication-options-master.html#sysvar_auto_increment_increment 。主要是控制 auto_increment 屬性的列每次自增的值的間隔。比如從1 3 5 7 增長的時候,auto_increment_increment 可以設定為2.

  4)接著就是後面的剩餘操作。

 

從這裡可以看出,如果是一個新的JDBC 連線,它就需要這個請求過程,是不可避免的。那麼如果儘量減少 Client 的請求呢。現在常用的就是使用 DB 連線池技術。

 

正巧開發的同時配置的資訊如下:

<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="UNPOOLED">
                <property name="driver" value="${db.driverClass}" />
                <property name="url" value="${db.connectUrl}" />
                <property name="username" value="${db.user}" />
                <property name="password" value="${db.pass}" />
            </dataSource>
        </environment>
    </environments>

最後推斷是 <dataSource type="UNPOOLED"> 這個引數的設定問題。其中type 有三個可選值: type="[UNPOOLED|POOLED|JNDI]" 通過 http://www.mybatis.org/mybatis-3/configuration.html  的解釋可以看到  UNPOOLED – This implementation of DataSource simply opens and closes a connection each time it is requested.

後面讓開發把配置改為  type="POOLED", 測試發現仍然會出現上面的 SQL 請求,頻率會小一點。現在理解為:雖然有了連線池,但是第一次JDBC 連線的建立還是需要請求 MySQL variables 值的,只是後面重用連線的時候就沒有必要再去獲取這些值了。

 

結論:

1).通過JDBC 連線資料庫的時候,儘量配上連線池,不然每次訪問都需要額外的獲取的變數,也是很消耗資源的。

2).連線池第一次建立連線的過程大體上如下,不同jdbc 版本不同,可能請求會有略微差別。

3).這是一個正常現象。

 

還有一個疑問:下面的一個命令充斥著 MySQL slow query log。有人說是 client 來測試和資料庫的連通性的。可是能不能換個其他方式來測試呢?用這個 SQL 會讓我的 slow query log 全部是這個玩意兒,很煩人。

 

# Time: 161122 11:21:01
# User@Host: db[db] @  [ip]
# Query_time: 0.000018  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 0 Logical_reads: 0 Physical_reads: 0
SET timestamp=1479784861;
# administrator command: Ping;

  

 

 

 

 

相關文章