事务是一组不可分组的操作集合,这些操作要么都成功执行,要么都取消执行。最典型的需要事务的场景是银行账户间的转账:假如A账户要给B账户转账元,那么A账户要扣减元,B账户要增加元,这两个账户的数据变更都成功才可算作转账成功。
本文涉及到MySQL锁机制的很多知识,对这方面不了解的可以先看博客《快速理解MySQL的锁机制与死锁排查》
ACID原则
事务具有四个原则:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这四个特性简称为ACID原则。
原子性(Atomictiy):事务是一个包含一系列操作的原子操作。事务的原子性确保这些操作全部完成或者全部失败。
一致性(Consistency):事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。
如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所作的修改有一部分已写入物理数据库,此时数据库就处于不一致的状态。(在合格的数据库产品中,数据库重启后,会按照一定规则回滚所有导致不一致的事务)
隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
持久性(Durabilit):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
1.原子性
原子性(Atomicity)的实现离不开MySQL的事务日志undolog日志类型,当事务需要回滚的时候需要将数据库状态回滚到事务开始前,即需要撤销所有已经成功执行的sql语句。undolog起了关键性作用。
当事务对数据库进行修改时,InnoDB会生成对应的undolog;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undolog中的信息将数据回滚到修改之前的样子。
undolog
undolog主要为事务的回滚服务。在事务执行的过程中,除了记录redolog,还会记录一定量的undolog。undolog记录了数据在每个操作前的状态,如果事务执行过程中需要回滚,就可以根据undolog进行回滚操作。单个事务的回滚,只会回滚当前事务做的操作,并不会影响到其他的事务做的操作。
undolog的作用:
为了保证数据的原子性,记录事务发生之前的一个版本,用于回滚,
通过mvcc和undolog实现innodb事务可重复读和读取已提交隔离级别。
其中,undolog分为:
insertundolog:insert操作中产生的undolog。
updateundolog:delete和update操作产生的undolog。
insert操作
因为insert操作的记录,只对事务本身可见,对其他事务不可见。故undolog可以在事务提交后直接删除,不需要进行purge操作,
delete操作
Delete操作在事务中并不是真正的删除掉数据行,而是一种DeleteMark操作,在记录上标识Delete_Bit,而不删除记录。是一种"假删除",之后通过purge线程删除。(原因是为了支持MVCC)
update操作
update分为两种情况:update的列是否是主键索引。
如果不是主键索引,在undolog中直接反向记录是如何update的。即update是直接进行的。
如果是主键索引,update分两部执行:先删除该行,再插入一行目标行。
与insertundolog不同的,updateundolog日志,当事务提交的时候,innodb不会立即删除undolog,会将该事务对应的undolog放入到删除列表中,之后通过purge线程删除。
因为后续还可能会用到undolog,例如隔离级别为repeatableread时的MVCC,事务读取的都是开启事务时的最新提交行版本,只要该事务不结束,该行版本就不能删除(即undolog不能删除),且undolog分配的页可重用减少存储空间和提升性能。
purge线程两个主要作用是:清理undo页和清除page里面带有Delete_Bit标识的数据行。
2.一致性
一致性是通过事务的原子性、持久性和隔离性来保证的。
原子性:语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的。实现主要基于undolog。
持久性:保证事务提交后不会因为宕机等原因导致数据丢失。实现主要基于redolog。
隔离性:保证事务执行尽可能不受其他事务影响。InnoDB默认的隔离级别是RR,RR实现隔离性主要基于锁机制(包含next-keylock)、MVCC(包括数据的隐藏列、基于undolog的版本链、ReadView)。
3.隔离性
隔离性是指事务内部的操作与其他事务是隔离的,详情可以看下面章节“事务并发问题”与“解决事务并发问题”。
4.持久性
持久性是指事务提交之后,所做的修改就会永久保存,不会因为系统故障导致数据丢失,
redolog
在innoDB的存储引擎中,事务日志通过redolog和日志缓冲实现。事务开启时,事务中的操作,都会先写入存储引擎的日志缓冲中,在事务提交之前,这些缓冲的redolog都需要提前刷新到磁盘上持久化,这就是日志先行机制(Write-AheadLogging)。当事务提交之后,在日志缓冲中映射的数据文件才会慢慢刷新到磁盘。此时如果数据库崩溃或者宕机,那么当系统重启进行恢复时,就可以根据redolog中记录的日志,把数据库恢复到崩溃前的一个状态。未完成的事务,可以继续提交,也可以选择回滚,这基于恢复的策略而定。
在系统启动的时候,存储引擎就已经为redolog分配一块连续的存储空间,以顺序追加的方式记录RedoLog,通过顺序IO来改善性能。redolog日志的大小是固定的,即记录满了以后就从头循环写。所有的事务共享redolog的存储空间,RedoLog按语句的执行顺序,依次交替的记录在一起。
缓冲的redolog刷新到磁盘上持久化,刷新频率由innodb_flush_log_at_trx_