这个读是指的快照读
,而不是当前读
,当前读是一种加锁操作,是悲观锁
。
那它到底是怎么做到读—写不用加锁
的,快照读
和当前读
又是什么鬼,跟着你们的贴心老哥
,继续往下看。
当前读、快照读都是什么鬼
什么是MySQL InnoDB下的当前读和快照读?
当前读
它读取的数据库记录,都是当前最新
的版本
,会对当前读取的数据进行加锁
,防止其他事务修改数据。是悲观锁
的一种操作。
如下操作都是当前读:
- select lock in share mode (共享锁)
- select for update (排他锁)
- update (排他锁)
- insert (排他锁)
- delete (排他锁)
- 串行化事务隔离级别
快照读
快照读的实现是基于多版本
并发控制,即MVCC,既然是多版本,那么快照读读到的数据不一定是当前最新的数据,有可能是之前历史版本
的数据。
如下操作是快照读:
- 不加锁的select操作(注:事务级别不是串行化)
快照读与mvcc的关系
MVCCC
是“维持一个数据的多个版本,使读写操作没有冲突”的一个抽象概念
。
这个概念需要具体功能去实现,这个具体实现就是快照读
。(具体实现下面讲)
听完贴心老哥
的讲解,是不是瞬间茅厕顿开
。
数据库并发场景
读-读
:不存在任何问题,也不需要并发控制读-写
:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读写-写
:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失
MVCC解决并发哪些问题?
mvcc用来解决读—写冲突的无锁并发控制,就是为事务分配单向增长
的时间戳
。为每个数据修改保存一个版本
,版本与事务时间戳相关联
。
读操作只读取
该事务开始前
的数据库快照
。
解决问题如下:
并发读-写时
:可以做到读操作不阻塞写操作,同时写操作也不会阻塞读操作。- 解决
脏读
、幻读
、不可重复读
等事务隔离问题,但不能解决上面的写-写 更新丢失
问题。
因此有了下面提高并发性能的组合拳
:
MVCC + 悲观锁
:MVCC解决读写冲突,悲观锁解决写写冲突MVCC + 乐观锁
:MVCC解决读写冲突,乐观锁解决写写冲突
MVCC的实现原理
它的实现原理主要是版本链
,undo日志
,Read View
来实现的
版本链
我们数据库中的每行数据,除了我们肉眼看见的数据,还有几个隐藏字段
,得开天眼
才能看到。分别是db_trx_id
、db_roll_pointer
、db_row_id
。
- db_trx_id
6byte,最近修改(修改/插入)事务ID
:记录创建
这条记录/最后一次修改
该记录的事务ID
。
- db_roll_pointer(版本链关键)
7byte,回滚指针
,指向这条记录
的上一个版本
(存储于rollback segment里)
- db_row_id
6byte,隐含的自增ID
(隐藏主键),如果数据表没有主键
,InnoDB会自动以db_row_id产生一个聚簇索引
。
- 实际还有一个
删除flag
隐藏字段, 记录被更新
或删除
并不代表真的删除,而是删除flag
变了
如上图,db_row_id
是数据库默认为该行记录生成的唯一隐式主键
,db_trx_id
是当前操作该记录的事务ID
,而db_roll_pointer
是一个回滚指针
,用于配合undo日志
,指向上一个旧版本
。
每次对数据库记录进行改动,都会记录一条undo日志
,每条undo日志也都有一个roll_pointer
属性(INSERT操作对应的undo日志没有该属性,因为该记录并没有更早的版本),可以将这些undo日志都连起来
,串成一个链表
,所以现在的情况就像下图一样:
对该记录每次更新后,都会将旧值放到一条undo日志中,就算是该记录的一个旧版本,随着更新次数的增多,所有的版本都会被roll_pointer
属性连接成一个链表
,我们把这个链表称之为版本链
,版本链的头节点就是当前记录最新的值。另外,每个版本中还包含生成该版本时对应的事务id,这个信息很重要,在根据ReadView判断版本可见性的时候会用到。
undo日志
Undo log 主要用于记录
数据被修改之前
的日志,在表信息修改之前先会把数据拷贝到undo log
里。
当事务
进行回滚时
可以通过undo log 里的日志进行数据还原
。
Undo log 的用途
- 保证
事务
进行rollback
时的原子性和一致性
,当事务进行回滚
的时候可以用undo log的数据进行恢复
。 - 用于MVCC
快照读
的数据,在MVCC多版本控制中,通过读取undo log
的历史版本数据
可以实现不同事务版本号
都拥有自己独立的快照数据版本
。
undo log主要分为两种:
- insert undo log
代表事务在insert新记录时产生的undo log , 只在事务回滚时需要,并且在事务提交后可以被立即丢弃
- update undo log(主要)
先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
需要这份系统化资料的朋友,可以点击这里获取
课程,涵盖了95%以上网络安全知识点,真正体系化!**
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新