在微服务大行其道的今天,按理说不应该有多数据源这种问题(嗯,主从库算是一个多数据源的很常见的场景。),但是也没人规定不能这样做。

就算有人规定的,曾经被奉为圭臬的数据库三大范式现在被宽表冲得七零八落,在很多场景下,其实是鼓励建立冗余字段的。

话说项目中需要用到图数据库,我们选用了Neo4j。

什么是图数据库,大概提一下。

众所周知,计算机里的图大部份情况下指的是graph而非picture。

图数据库使用图形化的模型进行查询,通过节点、边和属性等方式来表示和存储数据,支持增删改查(CRUD)等操作。

比如人与人之间的社交网络关系就是一个非常典型的图数据场景。每个人看作是一个节点,节点之间联系成边,关系(父子,单向双向关注,上下级等)就是属性。

在只有两层关系的时候,mysql比起图库更有优势(节点数不很大的情况),但一旦层级达到3级以上,层级越高,图库效率优势越明显。

一开始,Neo4j服务作为一个单独的微服务,暴露增删改查的功能出来。

公司业务是特殊的2G场景,全内网部署,在一个非常特殊的场景下,同事把Neo4j的功能直接集成到了主项目当中,这样就涉及到了同一个项目当中的多数据源以及相应的事务管理的问题。

这里权当做个记录。

多数据源配置

spring boot 2.7通过spring-boot-starter-data-neo4j集成进来的neo4j版本在4.+,需要jdk11, 我们的生产环境还停留在jdk8,

所以这里采用spring boot 2.0.1.RELEASE或者高版本的spring boot自定义版本的neo4j starter。

neo4j-jdbc-driver为3.4.0。

如果是不同的mysql/oracel数据库之间的多数据源配置还好一点,neo4j与spring boot的集成有很多种方法。

官方推荐直接使用driver,获取session进行数据库操作。此种方式,neo4j数据库连接实现了AutoCloseable,无需关闭,也没有连接池的概念。

但这样的话就得手动实现事务。所以考虑再三还是采用和mysql一样的,jdbc+mybatis的方式。

直接上代码吧。

连接配置信息

就是两个不同mysql数据库和一个neo4j数据库的连接配置。

既然是jdbc连接,那么neo4j的连接URL就是jdbc:neo4j:bolt://192.168.124.125:7687,然后驱动不一样,其它都是一样的。

点击查看代码
  1. server.port = 8657
  2. spring.datasource.pri.url = jdbc:mysql://192.168.1.1:3306/test?useSSL=false&characterEncoding=utf8&allowMultiQueries=true
  3. spring.datasource.pri.driver-class-name = com.mysql.cj.jdbc.Driver
  4. spring.datasource.pri.type = com.zaxxer.hikari.HikariDataSource
  5. spring.datasource.pri.initial-size = 30
  6. spring.datasource.pri.max-active = 101
  7. spring.datasource.pri.min-idle = 7
  8. spring.datasource.pri.max-wait = 60000
  9. spring.datasource.pri.password = 123456
  10. spring.datasource.pri.username = root
  11. spring.datasource.pri.druid.filters=stat,slf4j
  12. spring.datasource.sec.url = jdbc:neo4j:bolt://192.168.1.3:7687
  13. spring.datasource.sec.driver-class-name = org.neo4j.jdbc.bolt.BoltDriver
  14. spring.datasource.sec.type = com.alibaba.druid.pool.DruidDataSource
  15. spring.datasource.sec.password = 123456
  16. spring.datasource.sec.username = neo4j
  17. spring.datasource.sec.druid.filters=stat,slf4j
  18. spring.datasource.thr.url = jdbc:mysql://192.168.1.2:3306/test?useSSL=false&characterEncoding=utf8&allowMultiQueries=true
  19. spring.datasource.thr.driver-class-name = com.mysql.cj.jdbc.Driver
  20. spring.datasource.thr.type = com.alibaba.druid.pool.DruidDataSource
  21. spring.datasource.thr.initial-size = 30
  22. spring.datasource.thr.max-active = 101
  23. spring.datasource.thr.min-idle = 7
  24. spring.datasource.thr.max-wait = 60000
  25. spring.datasource.thr.password = 123456
  26. spring.datasource.thr.username = root
  27. spring.datasource.thr.druid.filters=stat,slf4j
  28. mybatis.mapper-locations = classpath:mapper/*.xml
  29. mybatis.configuration.cache-enabled = false
  30. mybatis.configuration.local-cache-scope = SESSION

这里只贴关键代码,重要的是思路。

文末有完整代码链接。

数据源配置

mysql1

mysql1配置在MybatisDsMysql1Config

  1. @Configuration
  2. @MapperScan(basePackages = "com.nyp.dao.mapper1", sqlSessionFactoryRef = "sqlSessionFactory1")
  3. public class MybatisDsMysql1Config {
  4. @Bean(name = "ds1")
  5. @ConfigurationProperties(prefix = "spring.datasource.pri")
  6. @Primary
  7. public DataSource ds1DataSource() {
  8. return new DruidDataSource();
  9. }
  10. @Bean(name = "sqlSessionFactory1")
  11. @Primary
  12. public SqlSessionFactoryBean sqlSessionFactory1(@Qualifier("ds1") DataSource dataSource) throws IOException {
  13. SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
  14. // 设置数据源
  15. sqlSessionFactoryBean.setDataSource(dataSource);
  16. // 设置MyBatis的配置文件
  17. ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  18. sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
  19. return sqlSessionFactoryBean;
  20. }
  21. @Bean("mysqlTransactionManager")
  22. public DataSourceTransactionManager transactionManager(@Qualifier("ds1") DataSource dataSource) {
  23. return new DataSourceTransactionManager(dataSource);
  24. }

这里差不多做了4件事。

  • 创建了名为ds1类型为DruidDataSource的DataSource
  • 根据DataSource创建SqlSessionFactoryBean
  • 给ds1数据源创建一个事务管理器DataSourceTransactionManager
  • @MapperScan(basePackages = "com.nyp.dao.mapper1", sqlSessionFactoryRef = "sqlSessionFactory1") 通过basePackages指定了ds1数据库的mybatis映射文件的目录,同时将sqlSessionFactory1注入。换句话说,凡是访问这个映射目录的操作,就是访问ds1数据库。 3个不同的数据库,分别对应3个不同的mapper目录。

网上很多的多数据源的配置,通过DataSourceContextHolder来存储多个数据源,然后手动切换或者AOP注解切换数据源,个人觉得这个操作挺麻烦的。

mysql2

现在已经配置好了mysql1的数据源,mysql2类似,复制一个MybatisDsMysql1Config出来做为MybatisDsMysql2Config.

将里面的所有bean name全部改掉,springboot全容器范围保持唯一。

neo4j

现在mysql1,2数据源都配置好了。配置MybatisDsNeo4jConfig的数据源跟上面一模一样。

不同的是事务管理器用DataSourceTransactionManager还是Neo4jTransactionManager。

  1. @Bean("transactionManager")
  2. @Primary
  3. public DataSourceTransactionManager neo4jTransactionManager(@Qualifier("dsNeo4j") DataSource dataSource) {
  4. return new DataSourceTransactionManager(dataSource);
  5. }
  6. @Bean("transactionManager2")
  7. @Primary
  8. public Neo4jTransactionManager neo4jTransactionManager(SessionFactory sessionFactory) {
  9. return new Neo4jTransactionManager(sessionFactory);
  10. }

如果要使用mysql和neo4j的混合事务那就要用DataSourceTransactionManager,因为neo4j访问使用的jdbc,如果事务管理器使用的是非jdbc的事务管理器,那neo4j的事务就不生效了。

如果不用混合事务,这里可使用 Neo4jTransactionManager,但最好是使用DataSourceTransactionManager,毕竟连接方式是JDBC。

然后再建3个mybatis mapper接口目录,不同的目录对应相应的数据库。

多数据源配置就此完成,经测试没有问题。

事务

可能有人要问了,之前Neo4j作为微服务的时候,按理说要有分布式事务的,不然怎么保证两边操作的一致性呢?

其实是没有添加分布式事务的。

首先图库调用是在最后面的操作,如果图库微服务调用返回非200的状态码,就抛出异常,事务回滚。

但如果是在中间或前面调用,比如先调用图库服务,再操作mysql失败,那么图库就无法回滚了。

这样的话还有跑批的操作,这步勉强算是一个最终一致性的操作吧。

  • 分布式领域,最终一致性,只会迟到,不会缺席。
  • 分布式的尽头是最终一致性。

关于事务的测试的统一说明。

spring @Test为了防止测试数据污染数据库,此时添加@Transactional的时候,默认@Rollback(value = true),即永远回滚。

所以最好添加一个接口进行测试。

如果非要用@Test测试,注意手动添加@Rollback并设置相应的value。

ChainedTransactionManager

ChainedTransactionManager并不能保证跨事务数据的原子性。官方的说法是在特定领域有用,而且不打算修复或者扩展。

spring 官方在2020年11月已经开始将ChainedTransactionManager标记为@Deprecated。这一决定引起了一些讨论。具体情况在这里。

https://github.com/spring-projects/spring-data-commons/issues/2232

有人在问,移除了过后,面对多数据源的事务问题应该怎么处理?这样不管不顾就移除啦,这一点都不酷。

spring-data的leader在后面的解答,重点是,spring cannot help。

机翻,将就看。

引入一个假装协调分布式事务的实用程序从一开始就是错误的。现在人们正在使用ChainedTransactionManager,假设它正确地做事情,并想知道为什么没有替代品。

迁移路径可以是完全使用XA和2PC(例如,使用带有JTA的Atomikos Transaction Manager)。或者,您可以以考虑部分提交的事务的方式设计业务代码。由于这是高度特定于您的领域的,因此Spring在这里无法提供帮助。

我自己测试了一下

  1. @Configuration
  2. public class ChainedTransactionManagerConfig {
  3. @Autowired
  4. private DataSourceTransactionManager mysqlTransactionManager;
  5. @Autowired
  6. private DataSourceTransactionManager mysqlTransactionManager3;
  7. @Bean(name = "multiTransactionManager")
  8. @DependsOn("sessionFactory")
  9. public ChainedTransactionManager multiTransactionManager() {
  10. return new ChainedTransactionManager(mysqlTransactionManager,mysqlTransactionManager3);
  11. }
  12. }
  1. @Transactional(value = "multiTransactionManager", rollbackFor = Exception.class)
  2. public void test(){
  3. Person person3 = new Person();
  4. person3.setName("张三3");
  5. person3Dao.insert(person3);
  6. Person person = new Person();
  7. person.setName("张三");
  8. personDao.insert(person);
  9. int a = 1/0;
  10. }

在这种情况下,确实是保证不了两个事务的完整性。

此路不通。

aop + aspect

我们可以定义一个切面,拦截一个自定义的注解,然后手动的开启各个事务,在try里执行目标方法,如果没有异常,就commit各个事务,否则在catch里面rollback各个事务。

定义注解

  1. import org.springframework.core.annotation.AliasFor;
  2. import org.springframework.transaction.TransactionDefinition;
  3. import org.springframework.transaction.annotation.Isolation;
  4. import org.springframework.transaction.annotation.Propagation;
  5. import java.lang.annotation.*;
  6. @Target({ElementType.FIELD, ElementType.METHOD})
  7. @Retention(RetentionPolicy.RUNTIME)
  8. @Inherited
  9. @Documented
  10. public @interface MultiTransaction {
  11. // 这里也可以仿照@Transactional加上这些参数
  12. // @AliasFor("transactionManager")
  13. // String value() default "";
  14. //
  15. // @AliasFor("value")
  16. // String transactionManager() default "";
  17. //
  18. // Propagation propagation() default Propagation.REQUIRED;
  19. //
  20. // Isolation isolation() default Isolation.DEFAULT;
  21. //
  22. // int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
  23. //
  24. // boolean readOnly() default false;
  25. }

定义切面

拦截@MultiTransaction方法。

  1. @Aspect
  2. @Component
  3. public class TransactionAspect {
  4. @Resource
  5. private DataSourceTransactionManager transactionManager;
  6. @Resource
  7. private DataSourceTransactionManager mysqlTransactionManager;
  8. /**
  9. * 牺牲了@Transactional的事务传播与隔离的丰富性 变成了默认级别
  10. * @param proceedingJoinPoint
  11. * @return
  12. */
  13. @Around("@annotation(MultiTransaction)")
  14. public Object multiTransaction(ProceedingJoinPoint proceedingJoinPoint) {
  15. TransactionStatus neo4jTransactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
  16. TransactionStatus transactionStatus = mysqlTransactionManager.getTransaction(new DefaultTransactionDefinition());
  17. try {
  18. Object obj = proceedingJoinPoint.proceed();
  19. mysqlTransactionManager.commit(transactionStatus);
  20. transactionManager.commit(neo4jTransactionStatus);
  21. return obj;
  22. } catch (Throwable throwable) {
  23. mysqlTransactionManager.rollback(transactionStatus);
  24. transactionManager.rollback(neo4jTransactionStatus);
  25. System.err.println("multiTransaction fail:"+ throwable);
  26. throw new RuntimeException(throwable);
  27. }
  28. }
  29. }

transactionManager.getTransaction(new DefaultTransactionDefinition())内部在判断事务隔离传播等后,会开启一个事务doBegin()(视当前事务传播与具体情况)。

这种情况牺牲了@Transactional的事务传播与隔离的丰富性,变成了默认级别。

当然也可以在注解当中加上相就的参数,将事务的各种属性传进来,再通过DefaultTransactionDefinition设置。

  1. DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
  2. definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
  3. definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
  4. definition.setReadOnly(true);

不过事务非默认级别的情况没有经过测试。不清楚具体表现。

另外要特别注意两个事务管理器开启和完成的顺序,先开启的后结束。不然联合事务就不会生效,而且会产生异常。

先开启后结束,这是一个典型的栈的应用场景,所以改造一下,用栈来存储事务管理器,先进后出。

这样就不用担心事务管理器顺序出错。

  1. @Aspect
  2. @Component
  3. public class TransactionAspect {
  4. @Resource
  5. private DataSourceTransactionManager transactionManager;
  6. @Resource
  7. private DataSourceTransactionManager mysqlTransactionManager;
  8. /**
  9. * 牺牲了@Transactional的事务传播与隔离的丰富性 变成了默认级别
  10. * @param proceedingJoinPoint
  11. * @return
  12. */
  13. @Around("@annotation(MultiTransaction)")
  14. public Object multiTransaction(ProceedingJoinPoint proceedingJoinPoint) {
  15. Stack<DataSourceTransactionManager> dtmStack = new Stack<>();
  16. Stack<TransactionStatus> tsStack = new Stack<>();
  17. TransactionStatus neo4jTransactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
  18. dtmStack.push(transactionManager);
  19. tsStack.push(neo4jTransactionStatus);
  20. TransactionStatus transactionStatus = mysqlTransactionManager.getTransaction(new DefaultTransactionDefinition());
  21. dtmStack.push(mysqlTransactionManager);
  22. tsStack.push(transactionStatus);
  23. try {
  24. Object obj = proceedingJoinPoint.proceed();
  25. while (!dtmStack.isEmpty()) {
  26. dtmStack.pop().commit(tsStack.pop());
  27. }
  28. return obj;
  29. } catch (Throwable throwable) {
  30. while (!dtmStack.isEmpty()) {
  31. dtmStack.pop().rollback(tsStack.pop());
  32. }
  33. throw new RuntimeException(throwable);
  34. }
  35. }
  36. }

XA(JTA) + atomikos

这是前面提到的spring-data官方推荐的方案。

Java事务API(JTA:Java Transaction API)和它的同胞Java事务服务(JTS:Java Transaction Service),为J2EE平台提供了分布式事务服务(distributed transaction)的能力。 某种程度上,可以认为JTA规范是XA规范的Java版,其把XA规范中规定的DTP模型交互接口抽象成Java接口中的方法,并规定每个方法要实现什么样的功能。

在DTP模型中,规定了模型的五个组成元素:应用程序(Application)、资源管理器(Resource Manager)、事务管理器(Transaction Manager)、通信资源管理器(Communication Resource Manager)、 通信协议(Communication Protocol)。

这里主要关注两个模块事务管理器(Transaction Manager简称TM)、通信资源管理器(Communication Resource Manager简称RM)

TM供应商:

  1. 实现UserTransactionTransactionManagerTransactionTransactionSynchronizationRegistrySynchronizationXid接口,
  2. 通过与XAResource接口交互来实现分布式事务。此外,TM厂商如果要支持跨应用的分布式事务,那么还要实现JTS规范定义的接口。
  3. 常见的TM提供者包括我们前面提到的application server
  4. 包括:jbossejb serverweblogic等,以及一些以第三方类库形式提供事务管理器功能的jotmAtomikos
  5. 这里使用atomikosatomikos提供了基于JTA规范的XA分布式事务TM的实现。

RM供应商:

  1. XAResource接口需要由资源管理器者来实现,XAResource接口中定义了一些方法,这些方法将会被TM进行调用,如:
  2. start方法:开启事务分支
  3. end方法:结束事务分支
  4. prepare方法:准备提交
  5. commit方法:提交
  6. rollback方法:回滚
  7. recover方法:列出所有处于PREPARED状态的事务分支

一些RM提供者,可能也会提供自己的Xid接口的实现。 比如mysql提供了MysqlXADataSource



DruidX提供了DruidXADataSource,集成了一些常用的数据库

Hikari中没有实现类似于HikariXADataSource的功能,它使用的是各数据库自定义的XA对象(MysqlXADataSource等)。而Neo4j并没有实现这种本地资源管理器。

所以这里使用两个不同的mysql数据库来演示XA + atomikos 实现多数据源下本地的事务。

mysql1的配置文件MybatisDsMysql1Config里面数据源配置部份由

  1. @Bean(name = "ds1")
  2. @DependsOn("druidXADataSource1")
  3. @Primary
  4. public DataSource ds1DataSource() {
  5. return new DruidDataSource();
  6. }

变成

  1. @Bean(name = "ds1")
  2. @DependsOn("druidXADataSource1")
  3. @Primary
  4. public DataSource ds1DataSource(@Qualifier("druidXADataSource1") DruidXADataSource dataSource ) {
  5. AtomikosDataSourceBean xaDataSource=new AtomikosDataSourceBean();
  6. xaDataSource.setXaDataSource(dataSource);
  7. xaDataSource.setUniqueResourceName("ds1");
  8. return xaDataSource;
  9. }
  10. /**
  11. * 注入DruidXADataSource,Druid对JTA的支持,支持XA协议,采用两阶段事务的提交
  12. * @return
  13. */
  14. @Bean(value = "druidXADataSource1")
  15. @ConfigurationProperties(prefix = "spring.datasource.pri")
  16. public DruidXADataSource druidXADataSource1(){
  17. return new DruidXADataSource();
  18. }

原来是注入配置直接生成一个DruidXADataSource数据源,现在多了一步将DruidXADataSource数注入到AtomikosDataSourceBean对象,将后者作为数据源。而后者可以开启二阶段事务提交。

mysql2数据源同理。

然后再配置JtaTransactionManagerConfig

  1. @Configuration
  2. @EnableTransactionManagement
  3. public class JtaTransactionManagerConfig {
  4. @Bean
  5. public UserTransaction userTransaction(){
  6. UserTransactionImp userTransactionImp = new UserTransactionImp();
  7. return userTransactionImp;
  8. }
  9. @Bean
  10. public TransactionManager atomikosTransactionManager() {
  11. UserTransactionManager userTransactionManager = new UserTransactionManager();
  12. userTransactionManager.setForceShutdown(true);
  13. return userTransactionManager;
  14. }
  15. @Bean("xatx")
  16. public JtaTransactionManager transactionManager(UserTransaction userTransaction,
  17. TransactionManager transactionManager) {
  18. return new JtaTransactionManager(userTransaction, transactionManager);
  19. }
  20. }

此时在方法上加入注解@Transactional(value="xatx")即可开启二阶段事务提交。

同时@Transactional表示默认事务管理器。不想开启二阶段事务提交的时候,value填入相应的事务管理器即可。

如@Transactional(value="mysqlTransactionManager")表示该方法只管理mysql1数据库的事务。

XA+Atomikos的缺点在于并发效率低,我没有经过性能测试,但是可以从源码当中看到,其每个阶段都使用了synchronized

此功能需要保证mysql当前连接用户的mysql XA_RECOVER_ADMIN权限。

如果没有通过以下命令赋予权限。

  1. GRANT XA_RECOVER_ADMIN ON *.* TO root@'%' ;
  2. flush privileges;

测试结果:异常情况下,两条记录都不插入

正常情况下,两条记录均插入

debug模式下,完整地事务过程日志如下:

点击查看完整日志
  1. [2023-06-14 11:57:41.802] WARN 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : Thanks for using Atomikos! Evaluate http://www.atomikos.com/Main/ExtremeTransactions for advanced features and professional support
  2. or register at http://www.atomikos.com/Main/RegisterYourDownload to disable this message and receive FREE tips & advice
  3. Thanks for using Atomikos! Evaluate http://www.atomikos.com/Main/ExtremeTransactions for advanced features and professional support
  4. or register at http://www.atomikos.com/Main/RegisterYourDownload to disable this message and receive FREE tips & advice
  5. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.default_max_wait_time_on_shutdown = 9223372036854775807
  6. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.allow_subtransactions = true
  7. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.recovery_delay = 10000
  8. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.automatic_resource_registration = true
  9. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.oltp_max_retries = 5
  10. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.client_demarcation = false
  11. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.threaded_2pc = false
  12. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.serial_jta_transactions = true
  13. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.log_base_dir = ./
  14. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.rmi_export_class = none
  15. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.max_actives = 50
  16. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.checkpoint_interval = 500
  17. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.enable_logging = true
  18. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.log_base_name = tmlog
  19. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.max_timeout = 300000
  20. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.trust_client_tm = false
  21. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: java.naming.factory.initial = com.sun.jndi.rmi.registry.RegistryContextFactory
  22. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.tm_unique_name = 192.168.124.20.tm
  23. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.forget_orphaned_log_entries_delay = 86400000
  24. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.oltp_retry_interval = 10000
  25. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: java.naming.provider.url = rmi://localhost:1099
  26. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.force_shutdown_on_vm_exit = false
  27. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : USING: com.atomikos.icatch.default_jta_timeout = 10000
  28. [2023-06-14 11:57:41.804] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.provider.imp.AssemblerImp] : Using default (local) logging and recovery...
  29. [2023-06-14 11:57:41.806] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.recovery.imp.FileSystemRepository] : baseDir ./
  30. [2023-06-14 11:57:41.806] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.recovery.imp.FileSystemRepository] : baseName tmlog
  31. [2023-06-14 11:57:41.806] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.recovery.imp.FileSystemRepository] : LogFileLock com.atomikos.persistence.imp.LogFileLock@73fdd3eb
  32. [2023-06-14 11:57:41.818] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XATransactionalResource] : ds1: refreshed XAResource
  33. [2023-06-14 11:57:41.827] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XATransactionalResource] : ds3: refreshed XAResource
  34. [2023-06-14 11:57:41.833] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionManagerImp] : createCompositeTransaction ( 10000 ): created new ROOT transaction with id 192.168.124.20.tm168671506182700001
  35. [2023-06-14 11:57:41.836] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Creating a new SqlSession
  36. [2023-06-14 11:57:41.838] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ba0c88f]
  37. [2023-06-14 11:57:41.841] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AbstractDataSourceBean] : AtomikosDataSoureBean 'ds3': getConnection()...
  38. [2023-06-14 11:57:41.841] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AbstractDataSourceBean] : AtomikosDataSoureBean 'ds3': init...
  39. [2023-06-14 11:57:41.846] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@2f3d51b4: calling getAutoCommit...
  40. [2023-06-14 11:57:41.846] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@2f3d51b4: calling toString...
  41. [2023-06-14 11:57:41.846] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.transaction.SpringManagedTransaction] : JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2f3d51b4] will be managed by Spring
  42. [2023-06-14 11:57:41.847] DEBUG 16900 [http-nio-8657-exec-1] [com.nyp.dao.mapper3.Person3Dao.insert] : ==> Preparing: insert into t_person(name) value(?)
  43. [2023-06-14 11:57:41.849] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionImp] : addParticipant ( XAResourceTransaction: 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D31 ) for transaction 192.168.124.20.tm168671506182700001
  44. [2023-06-14 11:57:41.849] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XAResourceTransaction] : XAResource.start ( 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D31 , XAResource.TMNOFLAGS ) on resource ds3 represented by XAResource instance com.mysql.cj.jdbc.MysqlXAConnection@4a7819e4
  45. [2023-06-14 11:57:41.850] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionImp] : registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@bc4a5276 ) for transaction 192.168.124.20.tm168671506182700001
  46. [2023-06-14 11:57:41.851] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@2f3d51b4: calling prepareStatement(insert into t_person(name) value(?))...
  47. [2023-06-14 11:57:41.861] DEBUG 16900 [http-nio-8657-exec-1] [com.nyp.dao.mapper3.Person3Dao.insert] : ==> Parameters: 张三3(String)
  48. [2023-06-14 11:57:41.862] DEBUG 16900 [http-nio-8657-exec-1] [com.nyp.dao.mapper3.Person3Dao.insert] : <== Updates: 1
  49. [2023-06-14 11:57:41.862] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ba0c88f]
  50. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Creating a new SqlSession
  51. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4d66d2a4]
  52. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AbstractDataSourceBean] : AtomikosDataSoureBean 'ds1': getConnection()...
  53. [2023-06-14 11:57:41.863] INFO 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AbstractDataSourceBean] : AtomikosDataSoureBean 'ds1': init...
  54. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@50bd3a33: calling getAutoCommit...
  55. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@50bd3a33: calling toString...
  56. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.transaction.SpringManagedTransaction] : JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@50bd3a33] will be managed by Spring
  57. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [com.nyp.dao.mapper1.PersonDao.insert] : ==> Preparing: insert into t_person(name) value(?)
  58. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionImp] : addParticipant ( XAResourceTransaction: 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D32 ) for transaction 192.168.124.20.tm168671506182700001
  59. [2023-06-14 11:57:41.863] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XAResourceTransaction] : XAResource.start ( 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D32 , XAResource.TMNOFLAGS ) on resource ds1 represented by XAResource instance com.mysql.cj.jdbc.MysqlXAConnection@30715028
  60. [2023-06-14 11:57:41.864] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionImp] : registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@bc4a5276 ) for transaction 192.168.124.20.tm168671506182700001
  61. [2023-06-14 11:57:41.864] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@50bd3a33: calling prepareStatement(insert into t_person(name) value(?))...
  62. [2023-06-14 11:57:41.864] DEBUG 16900 [http-nio-8657-exec-1] [com.nyp.dao.mapper1.PersonDao.insert] : ==> Parameters: 张三(String)
  63. [2023-06-14 11:57:41.865] DEBUG 16900 [http-nio-8657-exec-1] [com.nyp.dao.mapper1.PersonDao.insert] : <== Updates: 1
  64. [2023-06-14 11:57:41.865] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4d66d2a4]
  65. [2023-06-14 11:57:41.865] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ba0c88f]
  66. [2023-06-14 11:57:41.865] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ba0c88f]
  67. [2023-06-14 11:57:41.865] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4d66d2a4]
  68. [2023-06-14 11:57:41.865] DEBUG 16900 [http-nio-8657-exec-1] [org.mybatis.spring.SqlSessionUtils] : Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4d66d2a4]
  69. [2023-06-14 11:57:41.866] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@2f3d51b4: close()...
  70. [2023-06-14 11:57:41.866] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XAResourceTransaction] : XAResource.end ( 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D31 , XAResource.TMSUCCESS ) on resource ds3 represented by XAResource instance com.mysql.cj.jdbc.MysqlXAConnection@4a7819e4
  71. [2023-06-14 11:57:41.867] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.jdbc.AtomikosConnectionProxy] : atomikos connection proxy for com.mysql.cj.jdbc.ConnectionImpl@50bd3a33: close()...
  72. [2023-06-14 11:57:41.867] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XAResourceTransaction] : XAResource.end ( 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D32 , XAResource.TMSUCCESS ) on resource ds1 represented by XAResource instance com.mysql.cj.jdbc.MysqlXAConnection@30715028
  73. [2023-06-14 11:57:41.871] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XAResourceTransaction] : XAResource.rollback ( 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D31 ) on resource ds3 represented by XAResource instance com.mysql.cj.jdbc.MysqlXAConnection@4a7819e4
  74. [2023-06-14 11:57:41.872] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.datasource.xa.XAResourceTransaction] : XAResource.rollback ( 3139322E3136382E3132342E32302E746D313638363731353036313832373030303031:3139322E3136382E3132342E32302E746D32 ) on resource ds1 represented by XAResource instance com.mysql.cj.jdbc.MysqlXAConnection@30715028
  75. [2023-06-14 11:57:41.875] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionImp] : rollback() done of transaction 192.168.124.20.tm168671506182700001
  76. [2023-06-14 11:57:41.875] DEBUG 16900 [http-nio-8657-exec-1] [com.atomikos.icatch.imp.CompositeTransactionImp] : rollback() done of transaction 192.168.124.20.tm168671506182700001
  77. [2023-06-14 11:57:41.879] DEBUG 16900 [http-nio-8657-exec-1] [org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor] : Closed Neo4j OGM Session in OpenSessionInViewInterceptor
  78. [2023-06-14 11:57:41.881] ERROR 16900 [http-nio-8657-exec-1] [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ArithmeticException: / by zero] with root cause
  79. java.lang.ArithmeticException: / by zero
  80. at com.nyp.controller.DyController.test(DyController.java:54)
  81. at com.nyp.controller.DyController$$FastClassBySpringCGLIB$$2df3816d.invoke(<generated>)
  82. at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
  83. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
  84. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  85. at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
  86. at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
  87. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
  88. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
  89. at com.nyp.controller.DyController$$EnhancerBySpringCGLIB$$cfcd46ca.test(<generated>)
  90. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  91. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  92. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  93. at java.lang.reflect.Method.invoke(Method.java:498)
  94. at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
  95. at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
  96. at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
  97. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
  98. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
  99. at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
  100. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
  101. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
  102. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
  103. at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
  104. at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
  105. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
  106. at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
  107. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  108. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  109. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
  110. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  111. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  112. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
  113. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  114. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  115. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  116. at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
  117. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  118. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  119. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  120. at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
  121. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  122. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  123. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  124. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
  125. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  126. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  127. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  128. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
  129. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
  130. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
  131. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
  132. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
  133. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
  134. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
  135. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
  136. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
  137. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
  138. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
  139. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  140. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  141. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  142. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  143. at java.lang.Thread.run(Thread.java:748)
  144. [2023-06-14 11:57:41.885] DEBUG 16900 [http-nio-8657-exec-1] [org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor] : Opening Neo4j OGM Session in OpenSessionInViewInterceptor
  145. [2023-06-14 11:57:41.900] DEBUG 16900 [http-nio-8657-exec-1] [org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor] : Closed Neo4j OGM Session in OpenSessionInViewInterceptor

可以看到atomikos开启事务,获取代理数据库连接,回滚事务的过程。

另外,atomikos会在根目录下记录日志,两个文件分别是tmlog.lk,tmlog.log,多个实例写入相同的文件会报异常。

关闭此日志可通过配置spring.jta.atomikos.properties.enable-logging=false

源码地址:

https://github.com/nyingping/dydatasource

参考:

http://www.tianshouzhi.com/api/tutorials/distributed_transaction/385

mysql和neo4j集成多数据源和事务的更多相关文章

  1. springboot(二)整合mybatis,多数据源和事务管理

     -- 1.整合mybatis -- 2.整合多数据源 -- 3. 整合事务 代码地址:https://github.com/showkawa/springBoot_2017/tree/master/ ...

  2. 3分钟搞定SpringBoot+Mybatis+druid多数据源和分布式事务

    文章来自: https://blog.csdn.net/qq_29242877/article/details/79033287 在一些复杂的应用开发中,一个应用可能会涉及到连接多个数据源,所谓多数据 ...

  3. springBoot(13)---整合Druid实现多数据源和可视化监控

    SpringBoot整合Druid实现多数据源和可视化监控 先献上github代码地址:https://github.com/yudiandemingzi/springboot-manydatasou ...

  4. SpringBoot 集成MyBatis、事务管理

    集成MyBatis (1)在pom.xml中添加依赖 <!-- mybatis的起步依赖.包含了mybatis.mybatis-spring.spring-jdbc(事务要用到)的坐标 --&g ...

  5. MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认(转)

    Select…For Update语句的语法与select语句相同,只是在select语句的后面加FOR UPDATE [NOWAIT]子句. 该语句用来锁定特定的行(如果有where子句,就是满足w ...

  6. Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(四)

    当任何时候觉你得难受了,其实你的大脑是在进化,当任何时候你觉得轻松,其实都在使用以前的坏习惯. 通过前面的学习,你可能大致了解了Quartz,本篇博文为你打开学习SSMM+Quartz的旅程!欢迎上车 ...

  7. MySQL之视图、触发器、事务、存储过程、函数 流程控制

    MySQL之视图.触发器.事务.存储过程.函数 阅读目录 一 视图 二 触发器 三 事务 四 存储过程 五 函数 六 流程控制 MySQL这个软件想将数据处理的所有事情,能够在mysql这个层面上全部 ...

  8. Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(转)

    通过前面的学习,你可能大致了解了Quartz,本篇博文为你打开学习SSMM+Quartz的旅程!欢迎上车,开始美好的旅程! 本篇是在SSM框架基础上进行的. 参考文章: 1.Quartz学习——Qua ...

  9. day15(mysql 的多表查询,事务)

    mysql之多表查询 1.合并结果集 作用:合并结果集就是把两个select语句查询的结果连接到一起! /*创建表t1*/ CREATE TABLE t1( a INT PRIMARY KEY , b ...

  10. Spring MVC Hibernate MySQL Integration(集成) CRUD Example Tutorial【摘】

    Spring MVC Hibernate MySQL Integration(集成) CRUD Example Tutorial We learned how to integrate Spring ...

随机推荐

  1. js模拟下拉菜单

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Vue 路由导航守卫

    Vue 路由导航守卫 一:全局守卫 (1) router.beforeEach beforeEach((to, from, next) => {}) 接收三个参数,在路由切换成功之前调用 to ...

  3. 图与网络分析—R实现(三)

    最小生成树 (Minimum Spanning Tree) 应该大家都不陌生,Spanning 有跨越的意思,生成树一般来说每个节点都能访问到别的节点,是一个连通树.所以,一般考虑无向图里去造生成树. ...

  4. python入门教程之一 什么是python

    python简介 1 什么是python Python是一种计算机程序设计语言.你可能已经听说过很多种流行的编程语言,比如非常难学的C语言,非常流行的Java语言,适合初学者的Basic语言,适合网页 ...

  5. [网络/Linux]CentOS7:OpenSSH升级到7.9p1 | 含: 安装Telnet/OpenSSH【telnet/ssh】

    [Q0 OpenSSH/sshd/ssh/scp/sftp,及OpenSSL这些软件组件之间有什么联系吗?] 请跳转咱的另一篇博文,相信阅读完后,你会清楚很多: [网络/SSH]OpenSSH: ss ...

  6. [Linux]常用命令之【cat/echo/iconv/vi/grep/find/head/tail】

    cat cat [选项] [文件].. # 一次显示整个文件或从键盘创建一个文件或将几个文件合并成一个文件 cat -n file1 # 编号文件内容再输出 echo -n 输出后不换行 -e 遇到转 ...

  7. MySQL匿名空用户名处理

    问题描述:公司漏扫发现数据库内出现空用户名及密码,需要对这些用户进行整改 1.首先出现了疑问,这些空的用户名是怎么出现的,而且不附带密码. 2.可以手动这样创建这样的用户名和密码形式么. 3.如果能这 ...

  8. Go语言入门实战: 猜谜游戏+在线词典

    包含基础语法和入门Go语言的3个案例 速览基础语法 对于耳熟能详的顺序结构.分支结构(if else-if else.switch).循环结构(for)不作赘述. 数组: 长度固定的元素序列 pack ...

  9. Django笔记二十七之数据库函数之文本函数

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十七之数据库函数之文本函数 这篇笔记将介绍如何使用数据库函数里的文本函数. 顾名思义,文本函数,就是针对文本字段进行操作的函数,如下是目 ...

  10. Eclipse中添加Shell脚本(如start.sh)

    Eclipse中添加Shell脚本(如start.sh)       使用eclipse时,我们有时候会在自己的工程文件下添加一些脚本(比如将Qt代码在eclipse中运行生成moc文件时,或者要拷贝 ...