MySQL事务

ACID

事务,首先要了解 ACID

A 原子性

原子性体现在回滚上面,如果 SQL 执行出错,要把之前的状态恢复,那怎么知道恢复什么呢,把之前的状态保存在 undo log 里,出错则会执行相反的操作

C 一致性

事务执行完毕后,数据库的完整性约束并没有被破坏,主要是通过原子性 + 隔离性 + 持久性来保证

I 隔离性

写写操作是通过锁解决,写读操作是基于 MVCC

D 持久性

指的是事务一旦提交,对数据库的改变就是永久性的


MySQL 为了提高效率,会有一个 buffer,每次写到 buffer 中,再定期将 buffer 中的数据刷新到硬盘上,这就会有一个问题,如果 buffer 还没来得及刷盘,MySQL 宕机了,数据就会丢失,因此,引入了 redo log,当数据库的数据进行增删改的时候,先将 本次操作记录到 redo log 中,再写 buffer,这样如果宕机了,还有 redo log 来恢复数据,这样就保证了持久性

为什么 redo log 写数据要比 buffer 写数据库快?

因为 buffer 写盘是随机 IO,redo log 是追加的模式,是顺序 IO,效率就高,并且 buffer 持久化数据是以数据页 page 为单位的,默认是 16K,就是说一个数据页上的小小修改都要把整个数据页写入,redo log 只需要写入真正需要的部分,无效的 IO 就大大减少了,效率就提高了

读未提交:脏读,不可重复读,幻读都有可能出现

读已提交:避免脏读,可能出现不可重复读和幻读

重复读:避免脏读和不可重复读,可能出现幻读

串行化:全部避免,性能差

脏读: 一个事务修改了数据还没提交,另一个事务读到了旧数据

不可重复读: 一个事务多次读同一数据,间隔间,另一个事务把数据改了,导致两次读取结果不一样

幻读: 一个事务对全表数据进行修改,另一个事务往表中新增数据,修改完成后莫名其妙出现了没有修改到的数据

MySQL 的 InnoDB 默认是 RR,为什么可以解决幻读?

因为默认开启了间隙锁,这样就防止了两次 select 之间,有另外的事务进行增删操作