程序员,知道Mysql中事务ACID的原理吗?

引言

照例,我们先来一个场景~

面试官:"知道事务的四大特性么?"

OK,回到正题。说到事务的四大特性原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),懂的人很多。但是稍微涉及细节一点,这四大特性在数据库中的实现原理是怎么样的?那就没有几个人能够答得上来了。因此,我们这篇文章着重讨论一下四大特性在Mysql中的实现原理。

正文

我们以从A账户转账50元到B账户为例进行说明一下ACID,四大特性。

原子性

根据定义,原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做。即要么转账成功,要么转账失败,是不存在中间的状态!如果无法保证原子性会怎么样?数据不一致的情形,A账户减去50元,而B账户增加50元操作失败。系统将无故丢失50元~

隔离性

根据定义,隔离性是指多个事务并发执行的时候,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。如果无法保证隔离性会怎么样?

程序员,知道Mysql中事务ACID的原理吗?

如图所示,如果不保证隔离性,A扣款两次,而B只加款一次,凭空消失了50元,依然出现了数据不一致的情形!

ps:可能有细心的读者已经发现了,mysql中是依靠锁来解决隔离性问题。嗯,我们后面来说明。

持久性

根据定义,持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

如果无法保证持久性会怎么样?

设想一下,系统提示你转账成功。但是你发现金额没有发生任何改变,此时数据出现了不合法的数据状态,我们将这种状态认为是数据不一致的情形。

一致性

根据定义,一致性是指事务执行前后,数据处于一种合法的状态,这种状态是语义上的而不是语法上的。

如果无法保证一致性会怎么样?

实战解答

问题一:Mysql怎么保证一致性的?

但是,如果你在事务里故意写出违反约束的代码,一致性还是无法保证的。例如,你在转账的例子中,你的代码里故意不给B账户加钱,那一致性还是无法保证。因此,还必须从应用层角度考虑。

从应用层面,通过代码判断数据库数据是否有效,然后决定回滚还是提交数据!

问题二: Mysql怎么保证原子性的?undo logundo log名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的sql语句,他需要记录你要回滚的相应日志信息。

  • (1)当你delete一条数据的时候,就需要记录这条数据的信息,回滚的时候,insert这条旧数据

  • (2)当你update一条数据的时候,就需要记录之前的旧值,回滚的时候,根据旧值执行update操作

  • (3)当年insert一条数据的时候,就需要这条记录的主键,回滚的时候,根据主键执行delete操作

undo log记录了这些回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

ps:具体的undo log日志长啥样,这个可以写一篇文章了。而且写出来,看的人也不多,姑且先这么简单的理解吧。

问题三: Mysql怎么保证持久性的?redo log怎么解决这个问题?这么做有什么问题?

  • 只修改一个页面里的一个字节,就要将整个页面刷入磁盘,太浪费资源了。毕竟一个页面16kb大小,你只改其中一点点东西,就要将16kb的内容刷入磁盘,听着也不合理。

  • 毕竟一个事务里的SQL可能牵涉到多个数据页的修改,而这些数据页可能不是相邻的,也就是属于随机IO。显然操作随机IO,速度会比较慢。

于是,决定采用redo log解决上面的问题。当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将redo log中的内容恢复到数据库中,再根据undo logbinlog内容决定回滚数据还是提交数据。

采用redo log的好处?redo log进行刷盘比对数据页刷盘效率高,具体表现如下

  • redo log体积小,毕竟只记录了哪一页修改了啥,因此体积小,刷盘快。

  • redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。

ps:不想具体去谈redo log具体长什么样,因为内容太多了。

问题四: Mysql怎么保证隔离性的?t_balance

程序员,知道Mysql中事务ACID的原理吗?

其中id是主键,user_id为账户名,balance为余额。还是以转账两次为例,如下图所示

程序员,知道Mysql中事务ACID的原理吗?至于MVCC,即多版本并发控制(Multi Version Concurrency Control),一个行记录数据有多个版本对快照数据,这些快照数据在undo log中。

如果一个事务读取的行正在做DELELE或者UPDATE操作,读取操作不会等行上的锁释放,而是读取该行的快照版本。

总结

本文讲了Mysql中事务ACID四大特性的实现原理,希望大家有所收获。

--------  END  ---------

程序员,知道Mysql中事务ACID的原理吗?

最近面试BAT,整理一份面试资料Java面试BAT通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。关注公众号并回复 888 领取,更多内容陆续奉上。