我们使用MySQL主从设置来存储REST API中使用的数据 .

我们计划直接到master db-host或slave db-host依赖REST请求参数 .

为此,我们使用MySQL ReplicationDriver . 我们使用MyBatis作为DB和API之间的一层.Spring被用作IOC框架 .

我们已经定义了两个方法,它们从DB中检索数据的逻辑相同 . 这两种方法之间的区别仅在于,一种方法在@Transactional注释中具有“readOnly = true”,它将指向“slave”,另一种方法具有“readOnly = false”,它将指向“master” .

@Override
 @Transactional(value = "itemTrxManager", readOnly = true, rollbackFor = Exception.class)
  public Item getShopItemFromSlave(ItemGetKey itemKey, Options... opts) throws ItemException {
  ..
  }

 @Override
 @Transactional(value = "itemTrxManager", readOnly = false, rollbackFor = Exception.class)
  public Item getShopItemFromMaster(ItemGetKey itemKey, Options... opts) throws ItemException {
  ..
  }

但是我们注意到内部ReplicationDriver(MySQLConnection对象)始终指向它连接的第一个主机,并且在更改“readOnly”标志后不会更改 .

即:启动我们的API后,如果我们发送使用“slave”的请求,ReplicationDriver将使用“slave host”,即使我们改为使用“master”,它仍然指向“slave host” . 其他方面是相同的:启动我们的API后,如果我们发送请求使用“master”,ReplicationDriver将使用“master host”,然后如果更改为使用“slave”,它仍然指向“master host” .

请注意,所有日志(Apache DBCP,Spring DAO,MyBatis日志)显示它连接到正确的主机,但在调试之后我们发现问题出在MySQL驱动程序类中(MySQLConnection对象显示不正确的主机名).ie连接对象已从Apache DBCP DataSource和内部MySQLConnection对象显示不同的主机信息 .

例如,下面显示了我们日志中的一个片段 . 它说它连接到“slave”,当调试MySQL Driver内部类时,ReplicationDriver有关于“master”的信息 .

DEBUG [http-8080-2] [AbstractPlatformTransactionManager.java:365] - 使用名称[com.foo.bar.item.core.businesslogic.impl.MerchantCategoryBusinessLogicImpl.listMerchantCategory]创建新事务:PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'itemTrxManager'DEBUG [http-8080-2] [DataSourceTransactionManager.java:204] - 用于JDBC事务的获取连接[jdbc:mysql:// master-host:3301 /,UserName =item_user@10.9.203.50,MySQL Connector Java] DEBUG [http-8080-2] [DataSourceUtils.java:153] - 设置JDBC连接[jdbc:mysql:// master-host:3301 /,UserName =item_user @ 10.9.203.50,MySQL Connector Java]只读DEBUG [ http-8080-2] [Slf4jImpl.java:47] - 创建一个新的SqlSession DEBUG [http-8080-2] [Slf4jImpl.java:47] - 为SqlSession注册事务同步[org.apache.ibatis.session.defaults . DefaultSqlSession @ 329203a8] DEBUG [http-8080-2] [Slf4jImpl.java:47] - JDBC连接[jdbc:mysql:// slave-host:3306 /,UserName =item_user @ 10.9.203.50,MySQL Connector Java]将是由Spring DEBUG管理[http-8080-2] [Slf4jImpl.java:47] - ooo使用Connection [jdbc:mysql:// slave-host:3306 /,UserName =item_user @ 10.9.203.50,MySQL Connector Java] DEBUG [ http-8080-2] [Slf4jImpl.java:47] - ==>准备:选择商家来自glb_merchant_cat_tbl的_category_id,custom_category_id,merchant_id,parent_id,sibling_position,image_url,create_time,update_time,其中merchant_id =? . . . DEBUG [http-8080-2] [Slf4jImpl.java:47] - 事务同步提交SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@329203a8] DEBUG [http-8080-2] [Slf4jImpl.java:47] - 事务同步关闭SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@329203a8] DEBUG [http-8080-2] [DataSourceUtils.java:222] - 重置JDBC连接的只读标志[jdbc:mysql:/ / slave-host:3306 /,UserName=item_user@10.9.203.50,MySQL Connector Java] DEBUG [http-8080-2] [DataSourceTransactionManager.java:322] - 发布JDBC连接[jdbc:mysql:// master-host:事务DEBUG之后的3301 /,UserName=item_user@10.9.203.50,MySQL Connector Java] [http-8080-2] [DataSourceUtils.java:332] - 返回到DataSource的JDBC连接

如何解决这个问题呢?这可能是ReplicationDriver中的错误?

Update :

这是我们的 Spring 天背景:

<!-- this is needed for the annotated transactions to work -->
    <tx:annotation-driven transaction-manager="trx-manager-item" proxy-target-class="true" />

    <bean id="trx-manager-item" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="itemDataSource" />
        <qualifier value="itemTrxManager" />
    </bean>

连接网址:

jdbc:mysql:replication:// master-host:3301,master-slave:3301 / item2_1?allowMasterDownConnections = true&roundRobinLoadBalance = true&autoReconnectForPools = true

Context.xml:

<?xml version="1.0" encoding="UTF-8"?>

<Context>



<Resource name="jdbc/item"

auth="Container"

type="javax.sql.DataSource"

factory="com.foo.bar.dbcp.BasicDataSourceFactory"

driverClassName="com.mysql.jdbc.Driver"

defaultAutoCommit="false"

defaultTransactionIsolation="READ_COMMITTED"

removeAbandonedTimeout="600"

timeBetweenEvictionRunsMillis="60000"

minEvictableIdleTimeMillis="60000"

logAbandoned="true"

poolPreparedStatements="true"

removeAbandoned="true"

testOnBorrow="false" 

testOnReturn="false"

validationQuery="select null"

testWhileIdle="true"

/>

连接URL在com.foo.bar.dbcp.BasicDataSourceFactory类中设置 .