事务方法中使用truncate会发生什么

场景

在一个spring项目的事务方法中(使用@transactional注解):
首先执行一个delete语句;
然后执行一个truncate语句;
最后再执行一个insert语句;

问题:

为什么delete语句和truncate语句执行成功,但insert语句虽然执行了,却没有提交?

解释:

首先,在没有事务注解的方法中,一切与数据库的交互都是由mybatis处理的,
而mybatis默认是事务自动提交的,也就是每条sql语句执行完后会立即提交。

在添加事务注解后,应用与数据库的交互会由spring和mybatis共同处理(所以它们要共用同一个数据源):
spring管理事务,mybatis负责具体sql的执行。

那它们是如何协调的呢?
spring首先会在一开始创建连接开启事务,同时将连接放进当前线程(threadlocal);
mybatis执行sql语句时会从当前线程获取连接——这样就保证了spring和mybatis使用的是同一个连接;
mybatis执行sql后,会检查方法上是否有事务注解,如果有的话就不执行commit语句;
最后由spring执行commit。

这也就解释了一开始的问题:
执行完truncate后,当前事务已被提交(truncate虽然性能比delete好,但它是DDL语句,会触发事务提交),后续执行sql时,由于mybatis检测到事务注解所以不会提交
而spring此时早已把事务提交,也不会在方法结束时再一次提交了。(这里我以前理解的应该有问题:ddl触发提交是MySQL内部的机制,spring应该是没办法检测到的,它还是按正常的逻辑,在全部SQL执行后,调用commit操作,MySQL接受到命令后会检测到刚才的ddl语句已经提交过了,便会忽略ddl语句后面的操作——ddl语句虽然提交了事务,但并不会关闭,因为还没接受到用户的commit命令,所以ddl后面的语句在MySQL看来还是属于同一个事务里,只是它会忽略不执行而已。)

参考:https://www.cnblogs.com/Houz/p/11957908.html
https://www.cnblogs.com/guyaoblog/p/11421978.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值