欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > mysql的mvcc笔记

mysql的mvcc笔记

2024/10/24 13:35:17 来源:https://blog.csdn.net/d15514350208/article/details/143082481  浏览:    关键词: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博客

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com