来自:程序员小饭(ID:programmer_grow)
作者:饭米粒
此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,接下来咱们逐一总结
事务的特点:ACID原子性(Atomicity)「定义」
原子性的意思是指一个事务是一个无法分割的单位,事务中的操作要么都做,要么都不做;万一在事务中一个sql语句执行失败了,那么已执行的语句也必须回滚,数据库退回到执行事务之前的状态。其实简单来说,就是要么全部失败,要么全部成功
「实现原理」
原子性实现的关键是依据日志undolog,它是实现原子性的最关键的部分,是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚,靠的是undolog:当事务对数据库进行修改时,InnoDB会生成对应的undolog;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undolog中的信息将数据回滚到修改之前的样子。
undolog属于逻辑日志,它记录的是sql执行相关的信息。当发生回滚时,InnoDB会根据undolog的内容做与之前相反的工作:对于每个insert,回滚时会执行delete;对于每个delete,回滚时会执行insert;对于每个update,回滚时会执行一个相反的update,把数据改回去。
以update操作为例:当事务执行update时,其生成的undolog中会包含被修改行的主键(以便知道修改了哪些行)、修改了哪些列、这些列在修改前后的值等信息,回滚时便可以使用这些信息将数据还原到update之前的状态。
从上图可以了解到数据的变更都伴随着回滚日志的产生:
(1)产生了被修改前数据(zhangsan,)的回滚日志
(2)产生了被修改前数据(zhangsan,0)的回滚日志
根据上面流程可以得出如下结论:
每条数据变更(insert/update/delete)操作都伴随一条undolog的生成,并且回滚日志必须先于数据持久化到磁盘上所谓的回滚就是根据回滚日志做逆向操作,比如delete的逆向操作为insert,insert的逆向操作为delete,update的逆向为update等。回滚过程如图tips:undolog也可以这么理解
当delete一条记录时,undolog中会记录一条对应的insert记录当insert一条记录时,undolog中会记录一条对应的delete记录当update一条记录时,它记录一条对应相反的update记录
tips:逻辑日志和物理日志的区别看记日志的时候是针对一行记录,就是逻辑日志如果是一个数据页,就是物理日志
持久性(Durability)「定义」
事务一旦提交,其所做的修改会永久保存到数据库中,此时即使系统崩溃修改的数据也不会丢失。
「实现原理:Redolog(WALwriteaheadlog)」
先了解一下MySQL的数据存储机制,MySQL的表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘IO,然而即使是使用SSD磁盘IO也是非常消耗性能的。
为此,为了提升性能InnoDB提供了缓冲池(BufferPool),BufferPool中包含了磁盘数据页的映射,可以当做缓存来使用:读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取再放入缓冲池;
写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中(这一过程称为刷脏);
上面这种缓冲池的措施虽然在性能方面带来了质的飞跃,但是它也带来了新的问题,当MySQL系统宕机,断电的时候可能会丢数据!!!
因为我们的数据已经提交了,但此时是在缓冲池里头,还没来得及在磁盘持久化,所以我们急需一种机制需要存一下已提交事务的数据,为恢复数据使用。
于是redolog就派上用场了。下面看下redolog是什么时候产生的
既然redolog也需要存储,也涉及磁盘IO为啥还用它?
(1)刷脏是随机IO,因为每次修改的数据位置随机,但写redolog是追加操作,属于顺序IO。
(2)刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入;而redolog中只包含真正需要写入的部分,无效IO大大减少。
「redolog与binlog」
我们知道,在MySQL中还存在binlog(二进制日志)也可以记录写操作并用于数据的恢复,但二者是有着根本的不同的:
(1)作用不同:redolog是用于crashrecovery的,保证MySQL宕机也不会影响持久性;binlog是用于point-in-timerecovery的,保证服务器可以基于时间点恢复数据,此外binlog还用于主从复制。
(2)层次不同:redolog是InnoDB存储引擎实现的,而binlog是MySQL的服务器层(可以参考文章前面对MySQL逻辑架构的介绍)实现的,同时支持InnoDB和其他存储引擎。
(3)内容不同:redolog是物理日志,内容基于磁盘的Page;binlog的内容是二进制的,根据binlog_format参数的不同,可能基于sql语句、基于数据本身或者二者的混合。
(4)写入时机不同:binlog在事务提交时写入;redolog的写入时机相对多元:
前面曾提到:当事务提交时会调用fsync对redolog进行刷盘;这是默认情况下的策略,修改innodb_flush_log_at_trx_