Mysql中的快照读和当前读

mysql当前读和快照读(MVCC)

mysql读取数据实际上有两种读取模式:当前读和快照读

当前读:每次读取的都是当前最新的数据,但是读的时候不允许写,写的时候也不允许读。

快照读:读写不冲突,每次读取的是快照数据,

隔离级别Repeatable Read下(默认隔离级别):有可能读取的不是最新的数据

Read Committed隔离级别下:快照读和当前读读取的数据是一样的,都是最新的。

一. 相关知识

1.1 undolog

在操作数据之前,把需要操作的数据和事务记录备份到undo log中,目的就是为了保证原子性,如果一个事务执行中发生了故障,就可以通过undolog进行回滚

1.2 共享锁和排它锁

共享锁(S锁):共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。

如果事务T仅对数据A进行读取,那么会对数据A加上共享锁,之后则其他事务如果要读取数据A的话可以对其继续加共享锁,但是不能加排他锁(也就是无法修改数据)。获准共享锁的事务只能读数据,不能修改数据。

排他锁(X锁):用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。

如果事务T对数据A要进行修改,则需要对其添加排它锁,加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。

二. 当前读

Mysql实现当前读是通过共享锁+排他锁+Next-Key Lock实现的。

每次对行数据进行读取的时候,加共享锁。此时就不允许修改,但是允许其他事务读取,所以每次都可以读到最新的数据。

每次对行数据进行修改的时候,加排他锁,不允许其他事务读取和修改。这种情况下其他事务读取的数据也一定是最新的数据。

每次对范围行数据进行读取的时候,对这个范围加一个范围共享锁。

每次对范围行数据进行修改的时候,读这个范围加一个范围排它锁。

基于上述锁机制,实现当前读,确保每次读取的都是最新的数据。

三. 快照读

mysql中的快照读是通过MVCC+undolog实现的。

快照读,顾名思义,就是读取快照数据,也就是说当某个数据正在被修改的时候,也可以进行读取该数据,保证读写不冲突。

刚刚提到undolog,当我们对记录做了变更操作时,就会产生undo记录,undo记录中存储的是老版数据,当一个旧的事务需要读取数据时,为了能够读取到老版本的数据,需要顺着undo列找到满足其可见性的记录,这个找满足可见行的记录依赖。就是说每次都是读取undolog中的数据。

MVCC:

MVCC也称多版本并发控制,说的通俗易懂一点就是记录数据的不同版本。

实际上,不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,既链表,undo log的链首就是最新的旧记录,链尾就是最早的旧记录。

所以快照读都是去读取undolog中链首的最新的旧记录。

但是不同隔离级别下的快照读又有所区别。下面简单阐述

四. 不同隔离级别下的快照读

这里举例说明:

事务开始前 name = 张三 id = 1

事务A:select name from t where id = 1 (多次)

事务B:update name = 李四 from t where id = 1

在Read Committed隔离级别下,快照读和当前读读取的是一样的。因为每次select都会去读取最新的快照数据。

过程如下:

事务A开始

事务B开始

事务A select ,查出name = 张三

事务B update,修改name = 李四

事务B结束

事务A 再次select ,查出name = 李四 (因为此时undolog中的最新数据为李四)

事务A结束

在默认隔离级别Repeatable Read下,在一个事务内,读取的都是第一次select的数据,所以可能会出现读取的数据不是最新数据的情况

过程如下:

事务A开始

事务B开始

事务A select ,查出name = 张三

事务B update,修改name = 李四

事务B结束

事务A 再次select ,查出name = 张三 (因为只读第一次的快照数据)

事务A结束

相关推荐
IvorySQL3 小时前
PostgreSQL 日报 | JOIN 与外键优化(8 月 9 日)
数据库·postgresql
ltl3 小时前
自治数据库十年回顾:Peloton、NoisePage、OtterTune 到云原生 auto-tuning
数据库
灯澜忆梦4 小时前
【MySQL10】进阶篇 | 索引_#2性能优化
数据库·sql·mysql·性能优化
C++ 老炮儿的技术栈6 小时前
从 Qt Designer 属性编辑器的层级可以看到继承链
c语言·数据库·c++·qt·sqlite·visual studio
MC皮蛋侠客6 小时前
Redis 系列(一):全景与最小闭环——从 `SET` 命令到内存数据结构
数据结构·数据库·redis
zt1985q8 小时前
本地部署开源网络书签与内容管理工具 Karakeep 并实现外部访问
运维·服务器·网络·数据库·网络协议·开源
IvorySQL9 小时前
PostgreSQL 日报| PostgreSQL 19 默认 WAL 压缩算法(8 月 8 日)
数据库·postgresql·区块链
油丶酸萝卜别吃9 小时前
MySQL B+ 树查询全过程详解
数据库·mysql
leisoo80979 小时前
股票数据本地化存储实战:JSON、数据库与列式存储的方案对比
jvm·数据库·json
Exclusive_Cat9 小时前
MySQL回表机制解析与优化策略
数据库·sql