【问题标题】:Spring Boot JDBCTemplate with MySQL and Maria DB Commit and Rollback Issue带有 MySQL 和 Maria DB 提交和回滚问题的 Spring Boot JDBCTemplate
【发布时间】:2020-10-31 16:02:43
【问题描述】:

我正在使用带有 JDBCTemplate 的 Spring Boot 框架进行数据库访问。我使用 Transactional 注释来强制执行 DB 调用的事务。

@Transactional(rollbackFor = IllegalStateException.class, propagation = Propagation.REQUIRES_NEW)

使用 Maria DB,我可以在下面看到事务序列和我的事务回滚的日志,并且没有任何内容被提交。

o.s.j.d.DataSourceTransactionManager     : Creating new transaction with name [Test]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,-java.lang.IllegalStateException
o.s.j.d.DataSourceTransactionManager     : Acquired Connection [HikariProxyConnection@368558459 wrapping org.mariadb.jdbc.MariaDbConnection@3e839aa3] for JDBC transaction
o.s.jdbc.core.JdbcTemplate               : Executing SQL statement [INSERT INTO test (Col1,Col2) values(1,'ABC')]
o.s.j.d.DataSourceTransactionManager     : Initiating transaction rollback
o.s.j.d.DataSourceTransactionManager     : Rolling back JDBC transaction on Connection [HikariProxyConnection@368558459 wrapping org.mariadb.jdbc.MariaDbConnection@3e839aa3]
o.s.j.d.DataSourceTransactionManager     : Releasing JDBC Connection [HikariProxyConnection@368558459 wrapping org.mariadb.jdbc.MariaDbConnection@3e839aa3] after transaction

但是,使用 MySQl 5.1 数据库,我可以在日志中看到事务已回滚,但仍提交数据库更改。

在调试模式下,我能够看到发生 JDBC template.execute 调用的那一刻,记录被提交,并且 trscationManager 在我抛出显式检查异常并定义时收到回滚通知。

为什么回滚没有发生在 MySQL 中,而发生在 MariaDB 中?

我的 SQL 日志跟踪

DataSourceTransactionManager     : Creating new transaction with name [TEST]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'jdbcDataSourceTransactionManager'

DataSourceTransactionManager  : Acquired Connection [HikariProxyConnection@436329238 wrapping 
com.mysql.jdbc.JDBC4Connection@2b464384] for JDBC transaction
JdbcTemplate               : Executing prepared SQL update

JdbcTemplate               : Executing prepared SQL statement [INSERT INTO TEST (dataNetwork,start, end, type, directory, rank) values(?, ?, ?,?,?,?)]

DataSourceTransactionManager     : Initiating transaction rollback

DataSourceTransactionManager     : Rolling back JDBC transaction on Connection [HikariProxyConnection@436329238 wrapping 

com.mysql.jdbc.JDBC4Connection@2b464384]
DataSourceTransactionManager     : Releasing JDBC Connection [HikariProxyConnection@436329238 wrapping 

com.mysql.jdbc.JDBC4Connection@2b464384] after transaction
DispatcherServlet        : Failed to complete request: 
java.lang.RuntimeException: To Test Roll Back

服务方法代码:

@Transactional(transactionManager = "jdbcDataSourceTransactionManager")
public void copyDataNetwork(WorkingFolderCopyRequest workingFolderCopyRequest,
      DataNetworkTransaction transaction) throws RuntimeException {
    dataNetoworkDao.copy(DataNetworkTables.DATA_NETWORK.getTableName(),
       DataNetworkTables.DATA_NETWORK.getColumnName(),
        workingFolderCopyRequest.getSource(), 
 workingFolderCopyRequest.getDestination());

    throw new RuntimeException("To Test Roll Back");
}

DataNetworkDAO

@Repository
public class DataNetworkDAO  {

    private NamedParameterJdbcTemplate jdbcTemplate;

    @Autowired
    DataSource dataSource;

    public DataNetworkDaoImpl(@Qualifier("ooretaDataSource")DataSource dataSource) {
        this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    public void copy(String tableName, String dataNetworkColumn, String oldNetworkName, String newNetworkName) {
        String sql = "INSERT INTO TEST (dataNetwork,start, end, type, directory, rank) values(:dataNetwork, :start, :end,:type,:directory,:rank)";
        Map<String, Object> params = new HashMap<>();
        params.put("dataNetwork", "WF20");
        params.put("start", "2");
        params.put("end", "");
        params.put("type", "T");
        params.put("directory", "Temp");
        params.put("rank", 0);

        jdbcTemplate.update(sql, params);
        
    }
}

数据源配置

HikariPool-2 - 配置: allowPoolSuspension.............假 自动提交......................假 HikariPool-2 - 开始... HikariPool-2 - 添加连接 com.mysql.jdbc.JDBC4Connection@608eb42e HikariPool-2 - 启动完成。

o.h.e.j.e.i.JdbcEnvironmentInitiator : 数据库 -> 名称:MySQL 版本:5.1.73-社区主要:5 次要:1

o.h.e.j.e.i.JdbcEnvironmentInitiator:驱动程序-> 名称:MySQL 连接器 Java 版本:mysql-connector-java-5.1.25 (修订:${bzr.revision-id})主要:5 次要:1

【问题讨论】:

  • 添加用于每个 DB 的数据库驱动程序 - MariaDB 和 MySQL。
  • org.mariadb.jdbcmariadb-java-client2.1.2 mysqlmysql-connector-java5.1.49跨度>
  • @ShankarPS 知道为什么会这样吗?
  • 在调试期间我观察到 jdbacTemaplate.execute 调用在数据库中添加了我可以通过工作台查询的记录,下一个日志行是回滚但记录仍然存在。
  • 请添加以下内容。 1. MySQL 的日志跟踪。 2.方法的源码

标签: mysql spring-boot mariadb jdbctemplate


【解决方案1】:

经过一番挣扎,我找到了原因。我在这段 COVID 时间获得了程序员的快乐。

MySql 有 2 个数据库引擎 MyISAM 和 InnoDB。这个遗留数据库拥有所有带有 MyISAM 引擎的表。 MyISAM 引擎不支持事务。你不能回滚。

如果我们使用 SHOW TABLE STATUS;然后它将显示哪个表使用哪种引擎类型,然后我们需要如下更改表引擎以获得事务支持。

ALTER TABLE > ENGINE = 'InnoDB';

最后,回滚就像一个魅力。

阅读更多链接:

http://ronaldbradford.com/blog/using-rollback-with-myisam-2010-03-31/#:~:text=The%20MySQL%20default%20storage%20engine,at%20the%20delta%20over%20time.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-03
    • 2021-05-29
    • 2012-12-24
    • 2013-11-22
    • 2012-03-04
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多