InnoDB 啥时候不执行事务?

一、背景

最近看到技术群里,有朋友提的一个问题很有意思,值得简单探讨下。

InnoDB 啥时候不执行事务?

因此简单整理下,希望对大家有帮助。


该同学的回答是 “配置禁用事务”。

还有些同学说,可以“关闭 undo log 和 redo log”。


大家对这个问题怎么看呢?


二、结论先行

注: 以下只是自己的理解,可能会有纰漏,如果有不同意见,欢迎评论探讨。


InnoDB 引擎的所有语句都是在事务中执行的。


三、探讨

第一印象,Spring 里不启用事务相关的功能,如不使用 @Transaction 注解或者不使用编程式事务的方式不就好了吗?


因为平时我们开发的时候,“需要保证数据库操作的原子性时”,通常是加事务注解来实现的,“不需要事务”就不用事务注解。


果真如此?


如何“配置InnoDB 中关闭事务”,似乎没有办法。


遇事不决 *

https://*.com/questions/55014017/in-innodb-is-all-sql-in-the-transaction



在 InnoDB 引擎中,所有的活动都发生在事务中。 如果开启自动提交模式,每一个 SQL 语句都会在一个单独的事务中。 默认 MySQL

创建的连接都会开启自动提交,因此如果语句没有报错都会自动提交。如果执行的语句有错误,则会根据错误来决定是回滚还是提交。


如果开启自动提交模式,所有操作立即生效。如果设置不自动提交,则可以通过 COMMIT 来提交或者通过 ROLLBACK 来取消。 如果 autocommit 从 0 改为 1 ,那么事务中的操作将被自动提交。我们还可以使用 START TRANSACTION 或 BEGIN 语句来启动事务。


对应的 MySQL 官方文档

https://dev.mysql.com/doc/refman/5.6/en/innodb-autocommit-commit-rollback.html


By default, connection to the MySQL server begins with autocommit mode enabled, which automatically commits every SQL statement as you execute it.

(使用 InnoDB 引擎时)连接MySQl 服务时,自动提交模式是打开的,会自动提交你的每一个待执行 SQL 语句。


To use multiple-statement transactions, switch autocommit off with the SQL statement SET autocommit = 0 and end each transaction with COMMIT or ROLLBACK as appropriate. To leave autocommit on, begin each transaction with START TRANSACTION and end it with COMMIT or ROLLBACK.

如果想使用多语句事务(将多个语句放在一个事务中),可以使用 SET autocommit = 0,然后使用 COMMIT 或者 ROLLBACK 来提交事务即可;如果自动提交是打开状态,则可以先执行 START TRANSACTION ,然后执行多个 SQL 语句,最后使用 COMMIT 或者 ROLLBACK 来提交事务。


如果我们关闭自动提交,而且不执行开启事务的语句,会产生事务吗?


在关闭自动提交时,如果在显示开启事务前有待执行的 SQL 语句,则在显示开启事务时,之前的语句将被提交。

https://dev.mysql.com/doc/refman/8.0/en/innodb-autocommit-commit-rollback.html


在官方的例子可以看到, SET autocommit =0 后,执行两次插入和一次删除,然后再执行 ROLLBACK 命令,可以实现对两次插入和一次删除的回滚(如果不执行 ROLLBACK,直接通过 START TRANSACTION 显式开启事务,应该会自动提交 )。


其实,这也侧面印证了,在不自动提交状态下,未显示开启事务时,事务会隐式开启,只不过不会自动提交而已。


那么是否可以通过关闭 undolog 、redolog 开实现开启事务的目的呢?理论上可以,但暂时没找到关闭方法,即使有关闭方法,那这会导致 innoDB 引擎都无法工作而不是不开启事务。夸张点说,这和说关闭MySQL 服务就可以让 InnoDB 不执行事务差别不大。


其实我们使用 InnoDB 引擎时, 不将数据库的写操作包裹在 Spring 的事务注解中或者不适用 Spring 编程式事务,并不意味着没有用到InnoDB 的事务功能,只是意味着“这些操作没有放在同一个事务中执行”而已。


四、思考

1、遇到疑问以官方文档为准

2、如果不懂原理,只懂使用,很容易想当然

3、工作之余,多看看核心技术的官方文档和源码

4、实践是检验真理的标准,有时间尽量动手实践下

上一篇:封装复杂度之批量接口


下一篇:Java 单元测试获取目标日志内容进行断言的推荐姿势