前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot中@Transaction在不同MySQL引擎下的差异性

SpringBoot中@Transaction在不同MySQL引擎下的差异性

作者头像
是Vzn呀
发布2022-07-14 17:05:58
9990
发布2022-07-14 17:05:58
举报
文章被收录于专栏:架构悟道架构悟道

在springboot进行事务测试的时候,发现事务没有生效,在方法上添加了@Transactional注解并让方法先执行插入操作,接着再抛出个异常,触发事务回滚,代码如下:

代码语言:javascript
复制
@Transactional(propagation = Propagation.REQUIRED, rollbackFor =Exception.class)
public void executeSaveRollback(TestTable testTable) throwsException {
    repository.saveAndFlush(testTable);
    // 抛出异常,触发事务回滚
    throw new Exception("test throw exception and rollback the transaction...");
}

实际测试的时候发现,事务回滚并没有效果,数据已经插入到DB中:

搜索了下,发现有人提到说MySQL数据库的事务不生效,可能和引擎类型有关系,因此下一步往这个方向排查一下。

查看MySQL数据表的引擎类型

通过show create table TABLE_NAME命令查看MySQL中数据表对应的引擎类型,查询结果如下所示:

代码语言:javascript
复制
Table	Create Table
TestTable	CREATE TABLE `TestTable` (
  `uniqueId` bigint(20) NOT NULL,
  `objectDesc` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `objectName` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
  `CreateTime` datetime NOT NULL,
  `UpdateTime` datetime DEFAULT NULL,
  PRIMARY KEY (`uniqueId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

从上面的内容中可以看到ENGINE=MyISAM即表示了使用的是MyISAM引擎,所以测试代码中的事务回滚没有生效。

修改JPA自动创建表时的引擎

测试工程中,使用的是JPA自动创建数据表的方式,默认情况下,创建出来数据表使用的是MyISAM引擎,因此如果需要使用事务,可以手动配置下,指定使用InnoDB引擎进行创建数据表。

在SpringBoot的application.properties配置文件中,加入如下一行配置即可:

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

完整的JPA相关的配置参数如下:

代码语言:javascript
复制
# JPA Configure
# database type
spring.jpa.database=mysql
# whether to show the sql in the log or console
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

重新启动测试进程,然后再次执行show create table TABLE_NAME结果如下:

代码语言:javascript
复制
CREATE TABLE `TestTable` (
  `uniqueId` bigint(20) NOT NULL,
  `CreateTime` datetime NOT NULL,
  `objectDesc` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `objectName` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
  `UpdateTime` datetime DEFAULT NULL,
  PRIMARY KEY (`uniqueId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

可以发现已经是ENGINE=InnoDB了,上述修改生效。

再次运行测试工程,发现事务回滚生效了。

为什么事务对MyISAM引擎不生效呢

为什么Spring的事务无法控制MySQL的MyISAM引擎类型数据表操作呢?很显然,因为MyISAM引擎本身就是非事务安全的,它和InnoDB的介绍概述如下:

MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。与其他存储引擎比较,MyISAM具有检查和修复表格的大多数工具。MyISAM表格可以被压缩,而且它们支持全文搜索。它们不是事务安全的,而且也不支持外键。如果事物回滚将造成不完全回滚,不具有原子性。如果执行大量的SELECT,MyISAM是更好的选择。 InnoDB:这种类型是事务安全的。它与BDB类型具有相同的特性,它们还支持外键。InnoDB表格速度很快。具有比BDB还丰富的特性,因此如果需要一个事务安全的存储引擎,建议使用它。如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表,对于支持事物的InnoDB类型的表,影响速度的主要原因是AUTOCOMMIT默认设置是打开的,而且程序没有显式调用BEGIN开始事务,导致每插入一条都自动Commit,严重影响了速度。可以在执行SQL前调用BEGIN,多条SQL形成一个事物(即使AUTOCOMMIT打开也可以),将大大提高性能。

事务的影响范围

先看下测试的代码:

代码语言:javascript
复制
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void executeSave(TestTable testTable) {
    repository.saveAndFlush(testTable);
    System.out.println("save finished");
}

调用的代码如下:

代码语言:javascript
复制
@RequestMapping("/saveandflush3")
public String testSaveAndFlushData3(
        @RequestParam(value = "id")String id,
        @RequestParam(value = "name") String name,
        @RequestParam(value = "desc") String desc) {
    TestTable testTable = new TestTable();
    testTable.setId(Long.parseLong(id));
    testTable.setName(name);
    testTable.setDesc(desc);
    transactionTest.executeSave(testTable);
    return "";
}

打断点测试发现:当saveAndFlush方法执行完之后,数据库中并查询不到记录。只有在executeSave方法执行完成跳出此方法之后,即执行到调用逻辑中return ""语句的时候,数据库中才能查询到记录。由此可以看出,当@Transactional修饰的方法或者类执行结束跳出的时候,也即事务结束。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构悟道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 查看MySQL数据表的引擎类型
  • 修改JPA自动创建表时的引擎
  • 为什么事务对MyISAM引擎不生效呢
    • 事务的影响范围
    相关产品与服务
    数据库
    云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档