Репликация master/slave Mysql. Подключиться к мастеру даже для запросов на чтение? (делает ли драйвер "пинг" хозяином, прежде чем отправляться в рабство?)

Я использую репликацию master/slave mysql (запись в master и чтение на ведомые устройства) с URL-адресом ReplicationDriver.My следующим образом:

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

Я использую Spring + Spring модули MyBatis.

Я выполнил транзакцию как readOnly следующим образом:

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

Но когда я вижу журналы транзакций /db, это показывает, что даже для транзакций "readOnly" ReplicationDriver сначала запускает мастер. Обратите внимание на строки линий "Приобретение соединения" и "Отключение JDBC-соединения".

Почему это происходит?

1) Независимо от того, является ли его запрос только для чтения, продолжает ли драйвер JDBC "ping" -мастеру проверять, будет ли он жить, а затем перейти к подчиненному веществу для фактического запроса?

2) Если readOnly = true, не Spring установить readOnly (true) базового объекта Connection?

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>

Ответ 1

То, что вы видите, является побочным эффектом того, что драйвер JDBC MySQL управляет соединением (ами) с физическими серверами (будь то ведущий или ведомый). Ни пул соединений, ни менеджер транзакций Spring не знают о том, что соединение с базой данных разговаривает с несколькими серверами. Все выглядит так, как будто она работает правильно, но я объясню, почему это выглядит как основное соединение.

  • Во-первых, DBCP создает одно соединение JDBC через драйвер MySQL. Это соединение укажет на мастер, пока не будет установлено только для чтения, и в какой момент он переключится на подчиненный.
  • Во-вторых, Spring получает соединение из пула и записывает в журнал отладки, что он получил соединение. Поскольку соединение еще не установлено в режиме только для чтения, оно направит запросы к главному.
  • В-третьих, Spring изменяет соединение на режим только для чтения, в котором запросы точек будут перенаправлены на подчиненный.
  • Далее вашему приложению (или iBatis или w/e) предоставляется соединение для выполнения некоторой работы с базой данных.
  • После возврата элемента управления к Spring транзакция в соединении будет выполнена. Поскольку соединение находится в режиме только для чтения, вы можете увидеть отладочное сообщение транзакции, показывающее, что запросы будут направляться на подчиненный сервер.
  • Наконец, соединение reset перед возвратом в пул. Режим только для чтения очищается, и последнее сообщение журнала еще раз отражает, что соединение будет направлять запросы на главный сервер.

Надеюсь, это поможет. Если вам нужна более подробная информация, сообщите мне.