V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Aruforce
V2EX  ›  程序员

打算用 Spring AbstractRoutingDataSource 做一主多从 但是和事务搭配实现上感觉不太对头,怎么解决?

  •  
  •   Aruforce · Apr 6, 2021 · 1475 views
    This topic created in 1855 days ago, the information mentioned may be changed or developed.

    需求

    1. AbstractRoutingDataSource 想根据当前的事务状态来 routing 
    2. 在从库上禁用更新操作
    3. 每个请求 打在一个数据源上
    

    问题

    1. 在进行 data source routing 时,TransactionSynchronizationManager.isActualTransactionActive 总是返回 false ;按照代码的语义实际上是在事务之中的; 请问有什么其他的 API 可以使用么?
    2. 在 data source routing 中想向 TransactionSynchronizationManager 注册 TransactionSynchronization 用于资源清理,但是返回 synchronization is not active
    

    stackoverflow 似乎有人遇到了相同的问题

    https://stackoverflow.com/questions/9203122/routing-read-write-transactions-to-primary-and-read-only-transactions-to-replica

    Christophe Fondacci 这个回答。。似乎没有解决

    Supplement 1  ·  Apr 7, 2021

    搞定了。。。不要重写事务管理器。。。

    1. 重写 DataSourceTransactionManager的dobegin 方法 使用 如下代码来判断是否进入 事务;

    JdbcTransactionObjectSupport transaction1 = (JdbcTransactionObjectSupport) transaction;
            if (!transaction1.hasConnectionHolder() || transaction1.getConnectionHolder().isSynchronizedWithTransaction()){
                logger.info("it seems it is in transaction ");
    //do thread local bind  in transaction status
            }
    

    2. 重写 DataSourceTransactionManager的prepareSynchronization 方法

       @Override
        protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
            super.prepareSynchronization(status, definition);
            if (MasterSlavesDataSourceSynchronization.isInTransaction()){
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCompletion(int status) {
                      // do your thread local resource clean
                    }
                });
            }
        }
    

    3. 对 Connection 及 statement 以及 prepareStatement 的 更新及事务方法 进行 拦截 在 slave data source 上 直接 抛异常即可

    4. 要求更新 操作必须使用事务, 事务的所有操作都会route 到master,其余再无其他要求

    Supplement 2  ·  Apr 7, 2021
    不过要 重写事务管理器
    2 replies    2021-04-06 20:49:10 +08:00
    coderwl
        1
    coderwl  
       Apr 6, 2021
    直接用现成的吧,我司用的 sharding-jdbc , 写 /读操作自动路由到主 /从库,支持单库事务,可以看下
    Aruforce
        2
    Aruforce  
    OP
       Apr 6, 2021 via Android
    @coderwl 我不是要用 我是要做个改造…
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2813 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 13:53 · PVG 21:53 · LAX 06:53 · JFK 09:53
    ♥ Do have faith in what you're doing.