Hi,大家好,我是Mic,一个工作了14年的程序员和创业者。
今天分享的面试题很有意思,去大厂面试的时候,百分之90的可能性会问到。
但是真正能够完整回答出来的同学缺很少。
最近一个工作了11年的粉丝去面试,就被面试到这个问题。
问题是: Mysql事务的底层实现原理。
下面看看高手对这个问题的回答
需要高手面试文档(附赠大厂内部十万字面试文档)或者有不懂的技术面试题想咨询的小伙伴可以后台私信【Mic】或者评论区留言。
高手:
好的,面试官
Mysql里面的事务,满足ACID特性,所以在我看来,Mysql的事务实现原理,就是InnoDB是如何保证ACID特性的。
首先,A表示Atomic原子性,也就是需要保证多个DML操作是原子的,要么都成功,要么都失败。
那么,失败就意味着要对原本执行成功的数据进行回滚,所以InnoDB设计了一个UNDO_LOG表,在事务执行的过程中,
把修改之前的数据快照保存到UNDO_LOG里面,一旦出现错误,就直接从UNDO_LOG里面读取数据执行反向操作就行了。
其次,C表示一致性,表示数据的完整性约束没有被破坏,这个更多是依赖于业务层面的保证,数据库本身也提供了一些,比如主键的唯一余数,字段长度和类型的保证等等。
接着,I表示事物的隔离性,也就是多个并行事务对同一个数据进行操作的时候,如何避免多个事务的干扰导致数据混乱的问题。
而InnoDB实现了SQL92的标准,提供了四种隔离级别的实现。分别是:
RU(未提交读)
RC(已提交读)
RR(可重复读)
Serializable(串行化)
InnoDB默认的隔离级别是RR(可重复读),然后使用了MVCC机制解决了脏读和不可重复读的问题,然后使用了行锁/表锁的方式解决了幻读的问题。
最后一个是D,表示持久性,也就是只要事务提交成功,那对于这个数据的结果的影响一定是永久性的。
不能因为宕机或者其他原因导致数据变更失效。
理论上来说,事务提交之后直接把数据持久化到磁盘就行了,但是因为随机磁盘IO的效率确实很低,所以InnoDB设计了
Buffer Pool缓冲区来优化,也就是数据发生变更的时候先更新内存缓冲区,然后在合适的时机再持久化到磁盘。
那在持久化这个过程中,如果数据库宕机,就会导致数据丢失,也就无法满足持久性了。
所以InnoDB引入了Redo_LOG文件,这个文件存储了数据被修改之后的值,当我们通过事务对数据进行变更操作的时候,除了修改内存缓冲区里面的数据以外,还会把本次修改的值追加到REDO_LOG里面。
当提交事务的时候,直接把REDO_LOG日志刷到磁盘上持久化,一旦数据库出现宕机,
在Mysql重启在以后可以直接用REDO_LOG里面保存的重写日志读取出来,再执行一遍从而保证持久性。
因此,在我看来,事务的实现原理的核心本质就是如何满足ACID的,在InnDB里面用到了MVCC、行锁表锁、UNDO_LOG、REDO_LOG等机制来保证。
以上就是我对这个问题的理解!
总结
InnDB的事务实现原理,有很多可以借鉴的设计思想,
比如乐观锁、利用内存缓冲区的方式,以空间换时间的思想优化磁盘IO的性能等等
这些思想还挺重要的,比如在分布式事务框架Seata的AT模式的数据回滚,就借鉴了
InnDB里面UNDO_LOG的设计思想。
大家记得点赞收藏加关注。