目前分布式事务应用中使用的是动态数据源,通过对动态数据源A和B的操作发现可以正常插入回滚日志到对应数据源的undo_log表中,但是分布式事务回滚和提交时无法正确路由到对应的数据源对回滚日志和业务数据进行操作 场景描述: 应用1::事务参与方,通过动态数据源连接数据库,有默认数据源 应用2:事务发起方,无数据源配置,调用应用1的接口,通过传参动态对数据源进行操作 数据源A:业务表person 数据源B:业务表user 数据源C:默认数据源,seata-server配置此数据源,global_table, branch_table, lock_table在这
场景1:应用2通过调用两次应用1的dubbo接口进行A和B的数据库操作
新增person成功,新增user成功 数据源A和B分别插入一条undo_log 提交全局事务时,应用1报错:数据源C的undo_log表找不到(C里没有undo_log表) 数据源A和B的undo_log都没有删除 场景2:应用2通过调用两次应用1的dubbo接口进行A和B的数据库操作
新增person成功,新增user失败(主键冲突) 数据源A插入一条undo log 回滚全局事务时,应用1报错: 数据源C的undo_log表找不到 lock_table插入一条数据,但是resource_id的数据源为C(我认为应该为A) 全局事务回滚失败,A的undo log没有删除,person表的数据没有删除,C的lock_table的对应数据也没有删除 以下为报C数据源的undo_log找不到的堆栈信息 If there is an exception, please attach the exception trace:
2019-08-21 15:57:09.469 INFO 8568 --- [atch_RMROLE_8_8] io.seata.rm.AbstractRMHandler : Branch committing: 172.16.68.197:8091:2020086258 2020086260 jdbc:mysql://172.16.68.118:3306/zhttest null
2019-08-21 15:57:09.469 ERROR 8568 --- [atch_RMROLE_7_8] druid.sql.Statement : {conn-10001, pstmt-20433} execute error. SELECT * FROM undo_log WHERE branch_id = ? AND xid = ? FOR UPDATE
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'zhttest.undo_log' doesn't exist
at sun.reflect.GeneratedConstructorAccessor46.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2825)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2323)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:3188)
at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeQuery(FilterEventAdapter.java:465)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:3185)
at com.alibaba.druid.wall.WallFilter.preparedStatement_executeQuery(WallFilter.java:641)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:3185)
at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeQuery(FilterEventAdapter.java:465)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:3185)
at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.executeQuery(PreparedStatementProxyImpl.java:181)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:228)
at io.seata.rm.datasource.undo.UndoLogManager.undo(UndoLogManager.java:154)
at io.seata.rm.datasource.DataSourceManager.branchRollback(DataSourceManager.java:185)
at io.seata.rm.AbstractRMHandler.doBranchRollback(AbstractRMHandler.java:124)
at io.seata.rm.AbstractRMHandler$2.execute(AbstractRMHandler.java:68)
at io.seata.rm.AbstractRMHandler$2.execute(AbstractRMHandler.java:64)
at io.seata.core.exception.AbstractExceptionHandler.exceptionHandleTemplate(AbstractExceptionHandler.java:117)
at io.seata.rm.AbstractRMHandler.handle(AbstractRMHandler.java:64)
at io.seata.rm.DefaultRMHandler.handle(DefaultRMHandler.java:63)
at io.seata.core.protocol.transaction.BranchRollbackRequest.handle(BranchRollbackRequest.java:35)
at io.seata.rm.AbstractRMHandler.onRequest(AbstractRMHandler.java:149)
at io.seata.core.rpc.netty.RmMessageListener.handleBranchRollback(RmMessageListener.java:81)
at io.seata.core.rpc.netty.RmMessageListener.onMessage(RmMessageListener.java:71)
at io.seata.core.rpc.netty.AbstractRpcRemotingClient.dispatch(AbstractRpcRemotingClient.java:166)
at io.seata.core.rpc.netty.AbstractRpcRemoting$3.run(AbstractRpcRemoting.java:371)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
看起来是没有代理所有数据源, 需要代理每个数据源,然后Seata可以在回滚时正确路由。
您可以参考配置文件 DataSourceProxyConfig.java 以获得更多详细信息。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。