MySQL(事物下)

目录

[一 多版本并发控制( MVCC )是一种用来解决 读-写冲突 的无锁并发控制](#一 多版本并发控制( MVCC )是一种用来解决 读-写冲突 的无锁并发控制)

[1. 前置知识](#1. 前置知识)

示例:

[二 Read View](#二 Read View)

[1. 当事物进行快照读(读历史数据)会MySQL会创建一个Read Vidw类对象,用来记录和当前一起并发的事物(活跃的事物),主要用来判断哪些历史事物的操作能看到和不能看到,主要跟隔离级别有关。](#1. 当事物进行快照读(读历史数据)会MySQL会创建一个Read Vidw类对象,用来记录和当前一起并发的事物(活跃的事物),主要用来判断哪些历史事物的操作能看到和不能看到,主要跟隔离级别有关。)

[2. 下面是 Read View 的简化结构](#2. 下面是 Read View 的简化结构)

[三 验证读提交和可重复读](#三 验证读提交和可重复读)

下面是读提交场景:

下面是可重复读场景:

在可重复读的情况下,并发执行不能看到已经提交的事物。为什么?


一 多版本并发控制( MVCC )是一种用来解决 读-写冲突 的无锁并发控制

1. 前置知识

数据库并发场景:

  • 读 - 读:不对数据进行修改不需要加锁
  • 读 - 写:不对读事物进行保护,可能就会有脏读/幻读/不可重复读问题
  • 写 - 写:并发写势必是要加锁进行保护的

数据库绝大部分场景都是与读写有关,下面来看看不同的隔离级别情况下是如何做到让读写并发时读写事物分别获取的资源是不一样的?

  • 3个记录隐藏字段:创建表的时候会为表增加4个隐藏的字段行
  1. DB_TRX_ID : 6 byte ,记录最近对表的操作的事物ID
  2. DB_ROLL_PTR : 7 byte ,每次对表进行操作先会备份操作的内容,放到undo_log日志,然后用指针指向备份的内容,未来进行回滚操作
  3. DB_ROW_ID : 6 byte ,如果没有建立主键索引,会自动创建一个隐藏的主键列字段(构建B+树)
  • undo 日志:记录历史修改的操作
  • Read View:当进行快照读(读历史数据),会创建一个读视图,配合隔离级别用来判断哪些历史数据可以读,哪些不能读
示例:

记录历史修改后的数据,在定向回滚把历史数据拷贝覆盖到当前最新数据完成回滚操作,如果是新增,删除,则会记录相反的SQL语句。

二 Read View

1. 当事物进行快照读(读历史数据)会MySQL会创建一个Read Vidw类对象,用来记录和当前一起并发的事物(活跃的事物),主要用来判断哪些历史事物的操作能看到和不能看到,主要跟隔离级别有关。
2. 下面是 Read View 的简化结构
cpp 复制代码
class ReadView 
{
// 省略...
private:

trx_id_t m_low_limit_id; // 高水位,大于等于这个ID的事务均不可见

trx_id_t m_up_limit_id; //低水位:小于这个ID的事务均可见 */

trx_id_t m_creator_trx_id; //  创建该 Read View 的事务ID*/

ids_t m_ids; // 创建视图时的活跃事务id列表*/
// 省略...
};

m_creator_trx_id:创建该视图的事物ID

m_ids : 记录和该事务一起活跃的ID

m_up_limit_id : 记录活跃事物最小的ID

m_low_limit_id : 记录最新事物的ID+1,(3,6,9)分配9+1

在读取历史数据的时候,每条数据都会有记录该数据的事物ID字段,然后拿上该视图去比对历史的数据,哪些能看到,哪些不能看到,下面画图示例:

三 验证读提交和可重复读

假设有一行记录,同时有4个事物并发执行。

当事物2进行快照读之前,事物4已经提交,根据上面的描述,事物2应该看到事物4的修改(事物4不在活跃列表当中且不大于等于尚未被分配的事物4>4+1)

下面是读提交场景:

结论:在读提交的场景下并发执行中可以看到已经提交了的事物。

下面是可重复读场景:

结论:在可重复读的场景下并发执行中看不到已经提交的事物。

在可重复读的情况下,并发执行不能看到已经提交的事物。为什么?

因为当第一次快照读的时候生成READ VIEW 后续所有的读都会复用第一次形成的READ VIEW,所以即使提交了,但用的是第一次的快照,第一次的时候已经在活跃列表里,所以提交了也看不到。

但在读提交的表现可以看出:每次读的时候都会生成新的READ VIEW,新的读取生成的快照里的活跃列表已经不存在提交之后的事物了。

读提交和可重复读的区别:

读提交每次读取都会生成新的快照,可重复读每次读都会复用第一次读生成的快照。

相关推荐
一朝入魔3 小时前
oracle 中创建 socket客户端 监听数据库变动,返回数据给服务端!!!
数据库·oracle
洛北辰南4 小时前
系统架构设计师—案例分析—数据库篇—分布式缓存技术
数据库·分布式·系统架构·缓存技术
星光璀璨山河无恙5 小时前
【MySQL】数据库简要介绍和简单应用
数据库·mysql
px52133445 小时前
Solder leakage problems and improvement strategies in electronics manufacturing
java·前端·数据库·pcb工艺
啥都想学的又啥都不会的研究生6 小时前
Redis设计与实现-数据持久化
java·数据库·redis·笔记·缓存·面试
新知图书6 小时前
Windows下安装MongoDB 8
数据库·windows·mongodb
jay丿6 小时前
Django 分页操作详解
数据库·django·sqlite
誰能久伴不乏6 小时前
深入理解 Qt 系统托盘图标:创建自定义的系统托盘图标类
数据库·qt·microsoft
cherry52307 小时前
【第4章】项目实战-亿级电商系统需求分析
大数据·数据库·架构·需求分析