mysql的mvcc笔记

面试被问到mvcc,一脸懵逼,尴尬。查了查,记录下来;

事务特性ACID

原子性(Atomicity): 事务的操作不可分割,共同失败或成功。
隔离性(Isolation): 不同事物间相互不影响,称为隔离性,但是各个数据库实现时并不是直接完全隔离,事务执行的中间结果对其他事务是透明的,方便灵活使用
一致性(Consistency): 数据成功或者失败后和预设结果一致,即几个并行执行的事务,执行结果与按照串行执行结果一致。
**持久性(Durability):**事务成功后数据会持久化到磁盘,不会丢失。

隔离级别

事务的ACID的特性说了事务具有隔离性,而不同事务的隔离基本做法就是加锁。通过对锁的控制来实现事务的隔离性,其中Mysql默认的隔离级别是重复读(RR),而Oracle、Sql Server则是读已提交(RC);

读未提交: 可以读取其他事务未提交的数据,这个隔离性是最差的,一旦数据库的一条数据同时被多人操作就会出现问题
读已提交: 可以读取其他事务已经提交的数据,这个是Oracle的默认隔离级别
重复读: 不会读取到其他事务已经提交的数据(指当前事务已经读取到的数据),读到的数据都是本事务开始时的快照信息,被称为快照读。
**串行化:**所有事物完全隔离,互相不干扰,这也是最严格的隔离级别,注意串行化不同事物的读写也会阻塞。

参考 Mysql夺命50问-你的面试宝典_mysql explain 面试题-CSDN博客

事务问题分类:

脏读: 读到了其他事务未提交的数据

**不可重复读:**在一个事务操作中,读取到了其他事务提交的数据。

**幻读:**读到了其他事务新增的数据

隔离级别存在的问题

读未提交: 有脏读(读到了其他事务未提交的修改数据)、不可重复读(读到了其他事务已提交的修改数据)、幻读(读到了其他事务新增的数据)等全部问题,这个隔离级别啥问题都解决不了,所以没人用
读已提交: 解决脏读问题,但仍有不可重复读和幻读的问题
重复读: 解决脏读、不可重复读的问题,仍有幻读的问题
**串行化:**解决全部问题,就是效率太低

mvcc

什么是mvcc

MVCC,全称Multi-Version Concurrency Control,即多版本并发控制,是一种并发控制的方法,;

解决问题:

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
  • 解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题

mvcc原理

主要依赖于数据记录中的三个隐藏字段、undolog,read view来实现的。

1、隐藏字段

每行记录,除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段:

  • DB_ROW_ID:6字节,隐藏的主键,如果数据表没有主键,那么innodb会自动生成一个6字节的row_id
  • DB_TRX_ID:6字节,最近修改事务id,记录创建这条记录或者最后一次修改该记录的事务id
  • DB_ROLL_PTR:7字节,回滚指针,用于配合undo日志,指向上一个旧版本

假设记录如图所示:

2. undo log(回滚日志)

undo log是InnoDB的行为,主要用途是用于事务回滚和MVCC使用,在事务开始之前数据就会记录数据到undolog buffer(Buffer Pool中也是数据页形式存在)中,记录的是数据修改前的数据;

3. read view(快照读)

Read View是事务进行快照读操作的时候生产的读视图,在该事务执行快照读的那一刻,系统会生成一个此刻的快照,记录并维护系统此刻活跃事务的id,用来做可见性判断的,也就是说当某个事务在执行快照读的时候,对该记录创建一个Read View的视图,把它当作条件去判断当前事务能够看到哪个版本的数据,有可能读取到的是最新的数据,也有可能读取到的是当前行记录的undolog中某个版本的数据

1)可见性算法

将要被修改的数据的最新记录中的DB_TRX_ID(当前事务id)取出来,与系统此刻其他活跃事务的id去对比,如果DB_TRX_ID跟Read View的属性做了比较,不符合可见性,那么就通过DB_ROLL_PTR回滚指针去取出undolog中的DB_TRX_ID做比较,即遍历链表中的DB_TRX_ID,直到找到满足条件的DB_TRX_ID,这个DB_TRX_ID所在的旧记录就是当前事务能看到的数据。

2)可见性规则

首先要知道Read View中的三个全局属性:

  • trx_list:一个数值列表,用来维护Read View生成时刻系统正活跃的事务ID(1,2,3)
  • up_limit_id:记录trx_list列表中事务ID最小的ID(1)
  • low_limit_id:Read View生成时,系统即将分配的下一个事务ID(4)

当前读

读取的是最新版本的记录,读取时还要保证其它并发事务不能修改当前记录,会对读取的记录进行加锁

  • 共享锁:select lock in share mode
  • 排它锁:select for update 、update、 insert 、delete

RR 和RC 的快照读有什么区别

RR (可重复读)隔离级别下,则是同一个事务中的第一个快照读才会创建Read View,之后的快照读获取的都是同一个Read View.

在RC(读已提交)隔离级别下,是每个快照读都会生成并获取最新的Read View;

其他记录

mysql的日志

三种日志的区别:undo log、redo log 、bin log

其他日志:relay log(中继日志) 、general query log(一般查询日志)、慢查询日志、error log(错误日志)

Buffer pool(缓冲池)

InnoDB设计了一个缓冲池(Buffer Pool),来提高数据库的读写性能。

当读取数据时,如果数据存在于Buffer pool中,那么直接从Buffer pool中拿,否则从磁盘中拿。

修改数据时,如果数据存在于Buffer pool中,那么直接修改Buffer pool中数据所在的页,然后将其页设置为脏页,为了减少磁盘IO,不会立即将脏页写入磁盘,后续由后台线程选择一个合适的时机将脏页写入磁盘。

redo log

断电丢失问题:Buffer pool是基于内存的,如果断电重启,还未来的及写入磁盘的脏页数据就会丢失。 问题如何解决/

解决问题方法:

为了防止断电丢失的问题,当有一条记录需要更新时,InnoDB引擎就会先更新内存(同时标记为脏页),然后将本次对这个页的修改以redo log的形式记录下来,这个时候,更新就算完成。后续由后台线程选择一个合适的时机将脏页写入磁盘。

这就是:WAL(Write-Ahead Logging)技术:MySQL的写操作并不是立刻写在磁盘上,而是先写日志,然后在合适的时间再写入磁盘。

binlog 归档日志

undo log 和 redo log 是由InnoDB存储引擎 产生的

binlog 是由Server层 产生的,记录全部库表和数据的修改记录(不记录查询操作)

binlog有三种格式类型

STATEMENT(默认格式):记录SQL语句,但是存在动态函数的问题,比如获取当期时间、uuid
ROW:记录行数据最终被修改成什么样了。如果批量执行update语句,那可能会导致binlog文件过大。
MIXED:包含了上述两种模式,根据不同情况自动使用ROW和STATEMENT

bin log和redo log的区别:

  • 层次不同:redo log 是InnoDB存储引擎实现的,bin log 是MySQL的服务器层实现的,但MySQL数据库中的任何存储引擎对于数据库的更改都会产生bin log。

  • 作用不同:redo log 用于碰撞恢复(crash recovery ),保证MySQL宕机也不会影响持久性;bin log 用于时间点恢复(point-in-time recovery),保证服务器可以基于时间点恢复数据和主从复制。

  • 内容不同:redo log 是物理日志,内容基于磁盘的页**Page** ;bin log的内容是二进制,可以根据**binlog_format**参数自行设置。

  • 写入方式不同:redo log 采用循环写的方式记录;binlog 通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上。

  • 刷盘时机不同:bin log在事务提交时写入;redo log 在事务开始时即开始写入。

参考文章

​​​​​​一篇了解全MVCC - 程序员Forlan - 博客园

MySQL数据库七种日志介绍_mysql日志-CSDN博客

MySQL(日志)_mysql日志-CSDN博客

相关推荐
双子座断点14 分钟前
QStringList 使用详解
数据库
bw87672068722 分钟前
金融工程--pine-script 入门
数据库·金融
TT哇25 分钟前
【Java】数组的定义与使用
java·开发语言·笔记
三日看尽长安花1 小时前
【Redis:原理、架构与应用】
数据库·redis·架构
黑叶白树2 小时前
包和模块(上) python复习笔记
开发语言·笔记·python
L_Z_J_I2 小时前
超子物联网HAL库笔记:多指针定位+循环收发缓冲区方案设计
笔记
我是水怪的哥2 小时前
一些有用的科研数据网站
经验分享·笔记
zhilanguifang3 小时前
ERC论文阅读(02)--SAC;-LSTM论文阅读笔记
论文阅读·笔记·lstm
尘浮生3 小时前
Java项目实战II基于Spring Boot的美食烹饪互动平台的设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·微信小程序·小程序·美食
forestqq3 小时前
构建后端为etcd的CoreDNS的容器集群(七)、编写适合阅读的域名管理脚本
运维·数据库·etcd