Mysql主/从复制。即使对于读取查询,也要连接到master? (在去奴隶之前司机“ping”主人吗?)

时间:2014-03-19 03:39:20

标签: mysql spring jdbc database-replication spring-transactions

我使用ReplicationDriver使用mysql主/从复制(写入master并读取到slave)。我的连接URL如下:

"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.
    }

但是当我看到事务/数据库日志时,它显示即使对于" readOnly"事务ReplicationDriver首先命中master。 注意线条"获取连接"和#34;发布JDBC连接"线。

为什么会这样?

1)无论是否为只读查询,JDBC驱动程序是否仍然是" ping"主人检查它是否存在,然后转到奴隶进行实际查询?

2)如果readOnly = true,那么Spring是否设置了底层Connection对象的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/, UserName=root@10.174.10.72, 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/, UserName=root@10.174.10.72, 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/, UserName=root@10.174.10.72, MySQL Connector Java]
2014-03-19 12:32:31,382 DEBUG [http-8080-2] [DataSourceTransactionManager.java:322] - Releasing JDBC Connection [jdbc:mysql://master:3306/, UserName=root@10.174.10.72, 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 个答案:

答案 0 :(得分:13)

您所看到的是MySQL JDBC驱动程序正在管理与物理服务器(无论是主服务器还是从服务器)的连接这一事实的副作用。连接池和Spring事务管理器都不知道数据库连接与多个服务器通信的事实。一切看起来都正常,但我会解释为什么它看起来像是在使用主连接。

  • 首先,DBCP通过MySQL驱动程序创建单个JDBC连接。此连接将指向主站,直到设置为只读,此时它将切换到从站。
  • 其次,Spring从池中获取连接并写入已获取连接的调试日志。由于连接尚未设置为只读模式,因此它会将查询路由到主服务器。
  • 第三,Spring正在将连接更改为只读模式,此时查询将路由到从属设备。
  • 接下来,您的应用程序(或iBatis或w / e)将获得连接以执行数据库的某些工作。
  • 将控制权返回给Spring后,将提交连接上的事务。由于连接处于只读模式,因此您可以看到事务调试消息,显示查询将路由到从服务器。
  • 最后,在返回池之前重置连接。清除只读模式,最后一条日志消息再次反映连接将查询路由到主服务器。

希望这会有所帮助。如果您需要更详细的信息,请与我们联系。