读写分离用 AbstractRoutingDataSource 为什么经常不生效?readOnly 事务里写会怎样?内层 REQUIRES_NEW 走哪个库?这篇用同一个 MySQL 实例里的两个库代替主从,逐个实测。
DataSource 的类型:demo.Cfg$1(AbstractRoutingDataSource 的匿名子类)
@Transactional(readOnly = true) 的 readTx() ⇒ demo;determineCurrentLookupKey 被调用了 1 次,依次返回 [primary]
@Transactional 的 writeTx() ⇒ demo;determineCurrentLookupKey 被调用了 1 次,依次返回 [primary]
没有 @Transactional 的 noTx() ⇒ demo;determineCurrentLookupKey 被调用了 1 次,依次返回 [primary]
外层 readOnly 调 REQUIRED 的写方法 ⇒ 抛 TransientDataAccessResourceException:Connection is read-only. Queries leading to data modification are not allowed;determineCurrentLookupKey 被调用了 1 次,依次返回 [primary]
外层 readOnly 调 REQUIRES_NEW 的写方法 ⇒ 外层 readOnly 事务里 → 先读在 demo,再调 REQUIRES_NEW 的写方法,这次写在 demo;determineCurrentLookupKey 被调用了 2 次,依次返回 [primary, primary]
库 demo 的 log 表:(('writeTx',), ('from-readonly-outer-REQUIRES_NEW',))
库 replica 的 log 表:()路由在取连接时调用,而 readOnly 标记还没就绪,于是读到的是 false。
DataSource 的类型:org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
@Transactional(readOnly = true) 的 readTx() ⇒ replica;determineCurrentLookupKey 被调用了 2 次,依次返回 [primary, replica]
@Transactional 的 writeTx() ⇒ demo;determineCurrentLookupKey 被调用了 1 次,依次返回 [primary]
没有 @Transactional 的 noTx() ⇒ demo;determineCurrentLookupKey 被调用了 1 次,依次返回 [primary]
外层 readOnly 调 REQUIRED 的写方法 ⇒ 抛 TransientDataAccessResourceException:Connection is read-only. Queries leading to data modification are not allowed;determineCurrentLookupKey 被调用了 1 次,依次返回 [replica]
外层 readOnly 调 REQUIRES_NEW 的写方法 ⇒ 外层 readOnly 事务里 → 先读在 replica,再调 REQUIRES_NEW 的写方法,这次写在 demo;determineCurrentLookupKey 被调用了 2 次,依次返回 [replica, primary]
库 demo 的 log 表:(('writeTx',), ('from-readonly-outer-REQUIRES_NEW',))
库 replica 的 log 表:()外面包 LazyConnectionDataSourceProxy,推迟取连接;之后 readOnly 事务走从库,REQUIRES_NEW 的写方法走主库。