MySQL八股学习记录4事务的实现from小林coding

事务的概念与特性

概念:一个操作要么执行成功,要么回滚到执行前的状态
特性:ACID
原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成
一致性(Consistency):事务操作前和操作后,满足用户层的约束性
隔离性(Isolation):数据库允许多个事务同时对数据进行读写,隔离性可以保证多个事务同时读写的数据一致性
持久性(Durability):事务结束后,对事务的修改就是永久的,即使系统故障也不会丢失
事务四大特性的保证
持久性:redo log(重做日志)
原子性:undo log(回滚日志)
隔离性:MVCC(多版本并发控制)或锁机制实现的
一致性:通过持久 + 原子性 + 隔离性 保证

并行事务引发的问题

脏读

一个事务读到另一个未提交事务修改后的数据称为脏读
上图
脏读
场景:若A发生了回滚,那么B得到的数据是错误的数据

不可重复读

一个事务内对同一个数据的两次读取,读取到的数据不相同,称为不可重复读
不可重复读
场景:若A读取了数据,并且B提交了事务,那么A再次读取的数据就会与A上次读到的数据不一样

幻读

一个事务内多次查询Count,若两次的记录数量并不相同,那么发生了幻读现象
幻读
场景:事务B查询数据,之后事务A插入一条数据,并且提交,这个时候B再去读数据就会发现两次读取到的条数不一致,就像发生了幻觉一样

MySQL的应对策略

由于上述问题的存在,MySQL提出了四种隔离级别分别是

  • 读未提交:一个事务未提交,他的结果就能被其他事务看到
  • 读已提交:一个事务提交后,结果才能被其他事务看到
  • 可重复读:一个事务过程中看到的数据,与这个事务启动时看到的数据是一样的,InnoDB的默认隔离级别
  • 串行化:对记录加上读写锁,多个事务读写必串行
    在这里插入图片描述

InnoDB引擎可重复读详解

InnoDB引擎很大程度上的避免了幻读现象但并未完全避免方案有两种

  • 针对快照读(普通select),MVCC方式解决幻读:
  • 针对当前读(除了普通select都是这个读),next-key lock(记录锁+间隔锁)方式解决幻读

对于读提交和可重复读隔离级别的事务来说,通过Read View实现,读提交与可重复读的快照时间不同,可重复读是在每个事务之前生成一个快照,读提交是在每个语句前进行快照操作

ReadView在MVCC中的工作方式

ReadView有关的四个字段
聚簇记录中还有两个隐藏列

在这里插入图片描述
其中

  • trx_id:改动该数据的事务ID
  • roll_pointer:改变记录后,旧版本的记录将会被写入到undo日志中,通过该指针能找到旧版本的记录
    创建Read View后,记录中的trx_id可以划分成三种情况
    在这里插入图片描述
    一个事务访问记录时,自己更新的记录总是可见,其余情况下有
  • 如果记录的trx_id小于ReadView中的min_trx_id,那么表示该事务在创建ReadView之前生成,那么对当前事务可见
  • 如果记录的trx_id大于等于max_trx_id,那么这个版本的记录在创建ReadView后才生成,那么对该版本记录不可见,通过undolog去查找
  • 如果trx_id在ReadView的min_trx和max_trx之间,需要判断trx_id是否在m_ids列表中,若在,那么该版本的事务依然活跃,那么不可见,若不在,则已被提交,该版本的记录对当前事务可见

两种隔离级别通过MVCC实现

  • 可重复读是事务开始时就快照,整个事务期间都使用这个快照
  • 读已提交则是每次查询数据前生成新的快照

幻读被完全解决了吗

并没有,一种场景如下,事务A先查询一个数据,然后事务B插入一个数据,之后A再对该数据更新(虽然这样的操作很违和),这样之后A就能读B插入的数据,正因为这种特殊情况的存在,所以并不能认为MVCC解决了幻读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值