Mysql实现ACID特性

数据库ACID特性

  • 原子性(Atomicity)
    • 事务被视为不可分割的最小单元,而原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。(回滚通过回滚日志实现,日志中记录着事物所执行的修改操作,在回滚时,反向进行修改操作即可)
  • 一致性(Consistency)
    • 数据库在事务执行的前后都保持着一致性的状态,所有事务对一个数据的读取结果相同。
  • 隔离性(Isolation)
    • 一个事务所做的修改在最终提交前,对其他的事务是不可见的。
  • 持久性(Durability)
    • 一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

四大隔离级别及其实现原理

  • 三种导致产生不一致性的原因
    • 脏读:A,B两事务,A事务会读取到B事务未提交的数据,然后B因为某些原因回滚数据,所以A就读取了B没有提交的数据,也称脏数据。
    • 不可重复读:在A事务中对同一数据两次查询不一致,可能原因是在A事务提交之前B事务对该数据进行了操作
    • 幻读:类似于不可重复读,都是在一个事务周期内读的数据不一致,区别在于幻读是侧重于插入操作带来的影响,而不可重复读是编辑或者删除带来的影响
    • 丢失修改:一个事物的更新操作会被另一个事务的更新操作所覆盖。(需要实现串行化的隔离级别)。
  • 四种隔离级别
    在这里插入图片描述
  • 四种隔离级别的实现(当前读,快照读,MVCC,悲观锁,乐观锁)
    • 当前读
      • 当前读,所读取的是最新记录的数据,为保证其他并发事务不能修改当前记录,对读取的记录会枷锁。一般在执行select lock in share mode(共享锁), select for update ; update, insert,delete(排他锁)操作时使用(悲观锁)。也可采用乐观锁(控制版本号)进行手动实现。
      • 不可重复读只需采用行级锁就可防止该记录数据被更改或删除,而幻读则必须添加表级锁,来防止这个表中新增一条数据。
    • 哪些情况会加锁
      • 有索引并且使用了该索引当条件的时候就是行锁,没有索引的时候就是表锁。insert一般都是行锁, update ,delete和select差不多,能确定且走索引的是行锁,否则表锁。如果加了S锁,不影响查询,但会影响增加和修改,加了X锁,那么其他的事务涉及到这个数据就会陷入等待。
      • 也可手动执行命令来添加表锁,X锁和S锁。
    • 快照读
      • 不加锁的非阻塞读(即不加锁的select操作)是快照读。这基于MVCC进行实现。
    • 当前读与快照读都可实现四种隔离级别,但是在快照读中,串行化中会使用到间隙锁,进而退化成为当前读。
    • MVCC用于实现读提交读和可重复读这两种隔离级别,而再加上间隙锁则可实现串行化的隔离级别。
    • MVCC可以解决读写冲突上的四种隔离级别,而悲观锁和乐观锁进行写写冲突上的四种隔离级别,他们经常互相搭配使用。

MVCC

  • 多版本并发控制(MVCC)是MySQL的InnoDB存储引擎实现隔离级别的一种具体的方式,用来解决读写冲突。他的实现依赖于3个隐式字段,undo日志和Read View。
  • 隐式字段
    • DB_TRX_ID
      • 6byte,最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID
    • DB_ROLL_PTR
      • 7byte,回滚指针,指向这条记录的上一个版本(存储于rollback segment里)
    • DB_ROW_ID
      • 6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
  • undo log
    • insert undo log
      • 代表事务在insert新记录时产生的undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃。
    • update undo log
      • 事务在进行update或delete时产生的undo log; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除。
    • 每次不同事务对同一份内容的修改(加上排他锁),都会复制一份到undo log中,按照事务发生的顺序,对应的事务id不同(由一递增),最新修改的记录的指针会指向上一份记录。
  • Read View
    • Read View就是事务进行快照读操作的时候生产的读视图。其中记录了活跃的事务id(即未提交的事务)。Read View遵从当前事务id如果比最小的活跃事务id还小,则可见;如果比已出现的事务id还大,不可见;如果在活跃事务中,则代表未提交,不可见,否则可见。
  • RC,RR级别下的InnoDB快照读
    • 在RC级别下,事务中每一次的快照读,都会更新Read View,而RR级别下只会有第一个Read View,以后的快照读不再生成,而是基于第一个Read View。
  • 串行化级别下的快照读,则是在间隙锁的前提下进行的,使之不能插入数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值