MySQL事务特性ACID的实现原理

个人记录,请多多指教补充
1)原子性实现:是用undolog实现的,uodolog的意思是回滚日志,指的是每次在有写命令的时候,会先向undolog中写入一份,如果中间发生了故障,就可以通过uodolog进行回滚,比如说如果是insert命令只要delete就可以了,delete命令只要insert就可以了,update命令只要更新回原来的值就可以了

2)持久性实现:是用redolog实现的,意思是重做日志,mysql在读取或者修改数据的时候并不是直接进行读取修改的,而是用到了缓存的概念,因为如果每次读取修改都要对数据库进行操作,那么会对mysql造成压力,所以先对缓存进行操作,在对mysql进行操作,
如果要读取数据的话,是先去缓存中读取,如果缓存中没有,才去mysql中读取,然后再丢到缓存中去,修改数据的话也是先修改缓存,再修改数据库,但是这样的话就会出现问题,如果修改了缓存,但是还没有同步到数据库中去,这时候mysql宕机了,就会发生数据不一致的问题;
所以每次再有写命令的时候,先向redolog中写入,再写入缓存,要是mysql宕机了,我们也可以靠redolog进行恢复;

3)隔离性实现:隔离性的实现有两种方式,一种是锁机制,一种是MVCC多版本并发控制
锁机制的话就是加锁,行锁和表锁,加锁以后数据就不能被其他事务读取并且修改了,通过加锁的方式可以解决并发修改的问题,也就是写操作对写操作的影响

MVCC的话是多版本并发控制,在数据库的每一行后面都有一个隐藏的列,记录的事务的id和指向undolog的指针, undolog的指针又指向更早版本的undolog,通过隐藏的列和undolog可以把数据恢复到任一版本,然后还有一个readview,可重复读是在事务执行之后,第一个select语句之前生成readview,可以解决脏读,不可重复读,幻读的问题,读已提交是在事务执行之后,每个select之前生成readview,可以解决脏读的问题,但是解决不了不可重复读,幻读的问题(这里的话我本来是想举几个例子来说明一下,但是不知道怎么举,怕面试官理解不了我的想法)

它们是怎么解决的呢,是通过三方面的比较实现的,拿数据事务的id和下一个要分配的事务id(low_limit_id)进行比较,如果比low_limit_id小才可见,拿数据的事务id和当前活跃事务的最小id(up_limit_id)进行比较,如果比up_limit_id小才可见,可重复读会在事务执行之后,第一个select语句之前生成readview,保存了当前活跃事务的id,如果数据的事务id在活跃事务中,那么是不可见的,否则是可见的(这段话因为紧张没有说出来)

还有一种方式是加锁读,通过加共享锁和排他锁实现,共享锁的话是如果一个数据要读取数据,那么就会加共享锁,加了共享锁一种就只能加共享锁,不能再加排他锁;排他锁的话是一个事务如果要修改数据就会加排他锁,加了排他锁就什么锁都不能再加了,这样可以解决脏读,不可重复读的问题
如果要解决幻读的问题,还需要用到next-key lock,这个是行锁 和 间隙锁的结合,间隙锁指的是锁住一段数据的间隙,不锁存在的数据,next-key lock的话就是即要锁数据也要锁间隙,就可以解决幻读的问题;

4)一致性的实现:一致性的实现已经不能单纯靠日志实现了,而是要服务器层面 和 数据库本身实现

你可能感兴趣的:(mysql,数据库)