工作日记总结-transaction is aborted, commands ignored until end of transaction block
目录
- 问题描述
- 问题原因
- 总结
问题描述
公司一项目,之前员工在sql映射文件的一个标签内写了多条增删改语句,并通过begin、end包装起来,想的是手动开启事务;
<insert id="insertUser">begin;insert into users (id,name,pass) values ('1','qw','pass');insert into users (id,name,pass) values ('1','zdf','pass');insert into users (id,name,pass) values ('2','qfg','pass');end;</insert>
最近程序抛出异常,现象是查表数据时抛出异常
transaction is aborted, commands ignored until end of transaction block
问题原因
原因就在于没用的begin/end,手动开启显式事务,如果执行不出错,看不出问题,但是一旦sql中间执行报错,就会出现事务卡死的状态,没有机制可以rollback,释放当前事务;
如果java程序中没有捕获异常并处理,当前这个数据库连接就处于一个“脏”状态;
下一次再从数据库连接池中获取这个连接,执行sql时,就会抛出这个异常,意思是当前事务锁死,无法执行sql,除非rollback,把它回滚掉;
总结
- 在一个sql标签内,最好不要写begin、end,对于每个标签内的多条sql,mybatis/plus执行之前,会通过当前的sqlSession(封装的connection对象),设置当前数据库会话为自动提交事务,然后会将标签内的所有sql拼接成一个字符串发送给数据库
- 即使这个字符串包含了多条sql,数据库也会将它视为一个原子性的操作,数据库会开启一个隐式事务,都执行成功之后会自动提交,执行异常会自动回滚
- 因此,一个sql标签内的sql语句本身原子性的操作,无需通过begin/end手动开启事务,不仅无用,还会造成事务卡死,脏连接的问题;