MySQL里面的事务满足ACID的特性(A:atomicity原子性;C:consistency一致性;I:isolation隔离性;D:durability持久性)。
MySQL事务的原理就是让InnoDB如何保证ACID的特性(InnoDB:MySQL的默认存储引擎)。
首先A表示Atomic,也就是原子性,也就是说,需要保证多个DML操作的原子性,要么都成功,要么都失败,如果失败就意味着要对原本执行成功的数据进行回滚,所以InnoDB里面设计了一个undo log表,在事务执行的过程中,把修改之前的数据快照保存到undo log里面,一旦出现错误,就直接从undo log里面读取数据,进行反向操作就可以了;
其次是C表示consistency,也就是一致性,也就是说,数据的完整性约束不可以被破坏,我认为,这个更多的是依赖业务层面的一些保障,当然,数据库本身也提供了一些,比如说像主键的唯一性约束,字段长度和类型的一些保障等等;
接下来是I表示isolation,也就是事务的隔离性,也就是说多个并行的事务对同一个数据进行操作的时候,如何避免多个事务之间的干扰,导致数据混乱的问题,InnoDB里面提供了4中隔离级别的实现,分别是:
a、RU,也就是未提交读
b、RC,已提交读
c、RR,可重复读
d、Serializable,串行化
InnoDB默认采用的隔离级别是RR,也就是可重复读。然后使用了MVCC机制(即多版本并发控制,主要是为了提高数据库的并发性能)解决了脏读和不可重复读的问题,然后使用了行锁和表锁的方式来解决了幻读的问题;
最后一个是D表示durability,也就是持久性,也就是说,只要事务提交成功,那么对于这个数据的结果的影响一定是永久的,不能因为数据库宕机或者其他原因导致数据变更的失效。
理论上来说,事务提交之后直接把数据放到磁盘里就ok了,但是因为随机磁盘IO的效率确实很低,所以InnoDB里面设计了BufferPool缓冲区来进行优化,也就是说,数据发生变更的时候,先更新内存缓冲区,然后在合适的时间再持久化到磁盘里面,在这个机制里面,有可能出现在持续化过程中如果数据库宕机就导致数据丢失的情况,无法满足持久化,所以在InnoDB里面,引入了Redo log这样一个文件,这个文件存储了数据库变更之后的一个值,当我们通过事务进行数据变更的时候,除了修改内存缓冲区里面的数据以外,还会把本次修改的值追加到Redo log里面,当事务提交的时候,直接把Redo log里面的日志刷新到磁盘里面进行持久化,一旦数据库出现宕机,MySQL重启以后,可以直接用Redo log里面保存的重写日志,读取出来以后再去执行一遍,从而保证数据的持久性。
因此在我看来,事务的持久性原理核心本质就是如何去保证事务的ACID特性,而在undo log里面用到了MVCC、行锁、表锁、undo log以及redo log等等的机制去保证这样的特性。