2014-03-19 18 views
10

我用mysql主/從複製(寫掌握並讀取奴隸)與ReplicationDriver.My連接網址如下:Mysql主/從複製。即使讀取查詢連接到主設備? (做司機的「ping」師傅纔去奴隸?)

"jdbc:mysql:replication://master:3306,slave1:3307,slave2:3308/sampledb?allowMasterDownConnections=true" 

我用Spring + Spring MyBatis模塊。

我已經導致了我的交易爲只讀如下:

@Override 
    @Transactional(rollbackFor=Exception.class,readOnly=true) 
    public Sample getSample(SampleKey sampleKey) throws SampleException { 
     //Call MyBastis based DAO with "select" queries. 
    } 

但是,當我看到事務/ DB日誌,它表明,即使是「只讀」的事務ReplicationDriver首先撞擊高手。 注意行「獲取連接」和「釋放JDBC連接」行。

這是怎麼發生的?

1)不管它是否只讀查詢,JDBC驅動程序是否仍然「ping」master以檢查其是否存在,然後轉到slave以進行實際查詢? 2)如果readOnly = true,Spring不會設置底層連接對象的readOnly(true)嗎?

2014-03-19 12:32:28,280 DEBUG [http-8080-2] [AbstractPlatformTransactionManager.java:365] - Creating new transaction with name [com.rakuten.gep.foo.businesslogic.impl.SampleBusinessLogicImpl.getSample]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; '',-java.lang.Exception 
2014-03-19 12:32:28,390 DEBUG [http-8080-2] [DataSourceTransactionManager.java:204] - Acquired Connection [jdbc:mysql://master:3306/, [email protected], MySQL Connector Java] for JDBC transaction 
CACHED DAO 
Trying to retrive from the Cache 
2014-03-19 12:32:31,334 DEBUG [http-8080-2] [Slf4jImpl.java:47] - ooo Using Connection [jdbc:mysql://slave1:3307/, [email protected], MySQL Connector Java] 
2014-03-19 12:32:31,334 DEBUG [http-8080-2] [Slf4jImpl.java:47] - ==> Preparing: select tbl.item_id, tbl.item_name, tbl.create_time, tbl.update_time from sample_tbl tbl where tbl.item_id=? 
2014-03-19 12:32:31,335 DEBUG [http-8080-2] [Slf4jImpl.java:47] - ==> Parameters: 79bc3c80-af0a-11e3-a8e4-b8e8560f9d02(String) 
Adding SampleTbl id to cache : 79bc3c80-af0a-11e3-a8e4-b8e8560f9d02 
2014-03-19 12:32:31,340 DEBUG [http-8080-2] [AbstractPlatformTransactionManager.java:752] - Initiating transaction commit 
2014-03-19 12:32:31,342 DEBUG [http-8080-2] [DataSourceTransactionManager.java:264] - Committing JDBC transaction on Connection [jdbc:mysql://slave1:3307/, [email protected], MySQL Connector Java] 
2014-03-19 12:32:31,382 DEBUG [http-8080-2] [DataSourceTransactionManager.java:322] - Releasing JDBC Connection [jdbc:mysql://master:3306/, [email protected], MySQL Connector Java] after transaction 

我的連接設置爲:

<Context> 
    <WatchedResource>WEB-INF/web.xml</WatchedResource> 
    <Resource name="jdbc/sample" 
      auth="Container" 
      type="javax.sql.DataSource" 
      factory="org.apache.commons.dbcp.BasicDataSourceFactory"  
      username="root" 
      password="root" 
      driverClassName="com.mysql.jdbc.ReplicationDriver" 
      url="jdbc:mysql:replication://master:3306,slave1:3307,slave2:3308/sampledb?allowMasterDownConnections=true"  
      connectionCachingEnabled="true" 
      connectionCacheProperties="{MaxStatementsLimit=10}" 
      removeAbandoned="true" 
      removeAbandonedTimeout="600" 
      logAbandoned="true"    
      timeBetweenEvictionRunsMillis="1000" 
      minEvictableIdleTimeMillis="1000" 
      testOnBorrow="false" 
      testOnReturn="false" 
      validationQuery="select null" 
      testWhileIdle="true" 
      maxActive="10" 
      maxIdle="3" 
      maxWait="1000" 
      defaultAutoCommit="false"/> 

</Context> 

回答

11

你們看到的是一個事實,即MySQL JDBC驅動程序的管理連接(一個或多個)到物理服務器(無論是副作用主人或奴隸)。連接池和Spring事務管理器都不知道數據庫連接正在與多個服務器通信的事實。一切都看起來像正常工作,但我會解釋爲什麼它看起來像主連接正在使用。

  • 首先,DBCP通過MySQL驅動程序創建單個JDBC連接。這個連接將指向主設備,直到設置爲只讀模式,然後切換到從設備。
  • 其次,Spring正在從池中獲取連接並寫入已獲取連接的調試日誌。由於連接尚未設置爲只讀模式,因此會將查詢路由到主服務器。
  • 第三,Spring將連接切換到只讀模式,在此模式下查詢將被路由到從站。
  • 接下來,您的應用程序(或iBatis或w/e)被賦予連接以執行數據庫的一些工作。
  • 將控制權返回給Spring後,連接上的事務將被提交。由於連接處於只讀模式,因此可以看到事務調試消息顯示查詢將被路由到從服務器。
  • 最後,連接在被返回到池之前被重置。只讀模式被清除,並且最後的日誌消息再次反映連接將查詢路由到主服務器。

希望這會有所幫助。如果您需要更詳細的信息,請告訴我。

+0

感謝詳細的ansewr.my問題是,當我停止'主'時,讀取查詢需要太多的時間,因爲「連接主」和「釋放主」的兩個操作需要太長的時間。我試着減少了connectionTimeouts在上下文中。XML,但仍然需要太多時間。 –

+1

問題在於,每當連接返回到池時,MySQL複製驅動程序都會嘗試重新連接到主服務器。這發生在只讀模式被清除時。對於這種情況,我可以看到最簡單的解決方法是爲主服務器和從服務器使用單獨的數據源(和事務管理器)。您可以在註釋中指定(如果您需要,只讀屬性)數據源/事務管理器的名稱,例如: –

+0

@Transactional(「master」) –