首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MySQL的MyISAM模式导致事务回滚失效,将其改为InnoDB模式事务再次生效

MySQL的MyISAM模式导致事务回滚失效,将其改为InnoDB模式事务再次生效

原创
作者头像
黯然销魂
发布2025-10-15 16:34:56
发布2025-10-15 16:34:56
900
举报

公司的老系统是php开发的,而且是通过第三方授权的购买的,现在因为这种第三方的互联网产品在授权上很多都说得很模糊,让用户很多时候会踩坑,像有的刚开始说免费使用的,然而当你放心使用的时候突然接到律师函说侵权了……

吃过这种亏后,老板为了规避这种风险,决定重构一套,但是原先的客户数据实在太多了,所以打算基于原先系统的库表用java来做一套,这样也省得迁移数据之类的问题了。

然而在做的过程中发现当需要同时进行多张表操作的时候,去进行事务回滚数据库却没有回滚数据,明明在service中的方法都加了@Transactional注解,而且我人为抛出非检异常 int i=1/0;按理不应该不回滚。

代码语言:java
复制
@Service
public class UsersService {

    @Autowired
    private TUserMapper tUserMapper;

    @Transactional
    public void deleteUser(Long uid) {
        tUserMapper.deleteByPrimaryKey(uid);
        int i = 1 / 0;
    }

    @Transactional
    public void insertUser() {
        TUser tUser = new TUser();
        tUser.setName("bruce");
        tUserMapper.insert(tUser);

        tUser = new TUser();
        tUser.setName("bill");
        tUserMapper.insert(tUser);

        int i = 1 / 0;
    }
}

于是把工程中各种配置重新查了一遍,启动类配置类等等都查了一遍,把数据库挪到别的服务器上再试了几遍,还是不行。

代码语言:java
复制
@MapperScan("com.bruce.testmybatis.mapper")
@EnableTransactionManagement
@SpringBootApplication
public class TestMybatisApplication {
	public static void main(String[] args) {
		SpringApplication.run(TestMybatisApplication.class, args);
	}
}

后来干脆我新建一个Springboot+mybatisplus工程,再试了一遍,结果还是没有回滚数据。

想来想去可能不是代码的问题,会不会是数据库问题,毕竟一直在测试同一个数据库,即使到别的服务器上测试也是用的同步过去的数据库。于是我单独新建一个数据库,再跑几遍程序,结果所有的事务都正常执行……

被折磨了一天,居然是数据库的问题,实在是

WTF

于是我查了下原因,原先系统的数据库是php的工程自动化创建的,但是它自动创建的数据库引擎是 MyISAM,而这种引擎模式性能极佳,唯一的问题就是不支持事务。现在开发的系统对事务的要求越来越高,所以不可能再用MyISAM引擎模式,应该将其改为InnoDB引擎模式,InnoDB因为加了事务等一系列的功能后,这些记录事务的操作会占用一定的系统资源,而对于原先的数据并不会有什么影响。相反如果要从InnoDB转为MyISAM的话,可能会有点问题,因为MyISAM还不支持外键等约束……所以将MyISAM改为InnoDB除了对系统资源有影响外对数据基本不会有什么影响。

在服务器资源充裕且对数据没什么影响的情况下,果断将MyISAM转为InnoDB。因为一个MySQL数据库是允许部分MyISAM模式,部分InnoDB模式的,所以应该对表进行操作设置,通过下面SQL语句,会生成所有MyISAM模式的表

代码语言:sql
复制
SELECT CONCAT('ALTER TABLE ', table_schema, '.', table_name, ' ENGINE=InnoDB;')
   FROM information_schema.tables
   WHERE engine = 'MyISAM' AND table_schema NOT IN ('information_schema', 'performance_schema', 'mysql'); -- 排除系统库
image-20240419140846123
image-20240419140846123

将生成的语句全选,复制到查询面板,因为它生成的语句包含了服务器上所有数据库中的MyISAM模式的表,而我需要改的是wxsm数据库中的表,所以需要在查询面板中先筛选一下。

当我筛选好后执行命令,就批量将对应的表的模式由MyISAM改为InnoDB了。

image-20240419141311496
image-20240419141311496

这时候,再去执行service代码,所有的事务回滚全部生效。

开森

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • WTF
  • 开森
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档