mysql引擎与jdbc事务回滚

背景

最近在搭一个SSH框架的时候,测试hibernate + spring声明式事务的时候死活回滚不成功,反映的现象是不管抛出RuntimeException还是spring tx自己的DataAccessException都无法将已经插入的记录回滚掉,一开始是以为框架搭建的配置文件有问题,后来发现即使使用原生的jdbc rollback也无法回滚,此时才意识到可能是mysql数据库的问题。

分析

根据前面提到的思路,当SSH的事务无法正常回滚的时候也找不到配置的问题所在,就采用最简单的JDBC来测试一下事务回滚的是否正常,果然发现了问题。采用类似下面的代码,来做测试

@Test
    public void testTransaction()  {
        try {
            // 初始化mysql连接
            this.initMysql();
            // 设置不自动提交
            conn.setAutoCommit(false);
            Statement statement = conn.createStatement();
            // 执行插入
            statement.executeUpdate("insert into test VALUES(1,'a',18)");
            throw new RuntimeException("Test transaction exception");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            // 这里模拟捕捉类似spring事务管理的runtime exception
            System.out.println("Catched transaction exception");
            try {
                // 回滚,这是最关键的一行
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }
    }

运行该junit测试代码之后发现,虽然正常捕捉到了RuntimeException也执行了conn.rollback(),但是记录依然在表里面没有被回滚掉。这个时候仔细研究了一下这张表,发现建表语句为

CREATE TABLE `test` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

其他地方都正常,那唯一有可能出错的就是 ENGINE=MyISAM 这里了,查询资料后发现

MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。与其他存储引擎比较,MyISAM具有检查和修复表格的大多数工具。 MyISAM表格可以被压缩,而且它们支持全文搜索。它们不是事务安全的,而且也不支持外键。如果事物回滚将造成不完全回滚,不具有原子性。如果执行大量的SELECT,MyISAM是更好的选择。

明确说明了MyISAM不支持事务,这也就是问题的所在,把引擎改成InnoDB之后,上述测试代码就正常了。

总结

虽然MyISAM这个引擎不支持事务,但它并不是没有作用的,对于不需要事务的流水表或事实表,它就有更好的查询效率。 这里补充说明下两种引擎说明

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打 开也可以),将大大提高性能

附查询和修改的sql

查看mysql支持的所有存储引擎

show engines;

查看mysql当前默认的存储引擎

show variables like '%storage_engine%';

查看某个表用了什么引擎

在显示结果里参数engine后面的就表示该表当前用的存储引擎

show create table 表名;

修改引擎

ALTER TABLE my_table ENGINE=InnoDB

这里需要注意的是,如果表里面已经有数据了,且数据量大的时候进行修改可能会比较慢。如果数据比较重要,安全起见,可以采用将原数据表备份,新建InnoDB的数据表,再导入的形式来进行。

转载于:https://my.oschina.net/OttoWu/blog/1621611

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值