MySQL之事务隔离级别和MVCC

事务隔离级别

事务并发可能出现的问题

  • 脏写 事务之间对增删改互相影响
  • 脏读 事务之间读取其他未提交事务的数据
  • 不可重复读 一个事务在多次执行一个select读到的数据前后不相同。因为被别的未提交事务修改,删除数据或数据被更新被当前事务读取到了。
  • 幻读 一个事务在第一次读取正常数据,第二次读取到其他未提交事务的insert记录,导致读取一个不存在的记录。指一次读取读取到了之前未读取到的数据。

事务的4个隔离级别,以及解决的问题

  • READ UNCOMMITTED 未提交读 解决脏写
  • READ COMMITTED提交读 解决脏写、脏读
  • REPEATABLE READ可重复读 解决脏写、脏读、不可重复读
  • SERIALIAZBLE可串行化 解决脏写、脏读、不可重复读、幻读

四个隔离级别和可以解决的问题是SQL专门规定的,但是在Innodb引擎下,在可重复读的隔离级别的下就可以直接解决幻读的问题。

我们可以指定系统参数以在启动时修改系统的默认隔离级别,这在默认情况下是可重复的。

[En]

We can specify system parameters to modify the default isolation level of the system at startup, which is repeatable by default.

mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set, 1 warning (0.00 sec)

MVCC

版本链

我们在前面就讲过了undo日志,对于每次进行增删改就会产生undo日志,这时每个数据行的roll_pointer就会指向一个undo链表,我们就称其为版本链。我们在提一嘴,因为insert的undo日志在提交后是没有用的,所以在事务提交后insert的undo就会被释放。

可以到前面的文章了解一下undo日志。大概知道undo日志的类型和产生的过程就OK了感觉怎么存储undo日志的那一部分讲得云里雾里https://www.cnblogs.com/duizhangz/p/16333565.html

为什么没用?因为插入并不维护旧值,只是表明一个插入,并不需要存储什么信息。所以在事务提交时直接释放掉。因为事务在回滚时需要由一条insert语句类型的undo进行回滚。

MySQL之事务隔离级别和MVCC

这是上述两个事务生成的版本链。

[En]

This is the version chain generated by the above two transactions.

MySQL之事务隔离级别和MVCC

undo链表头存储的就是最新事务更新的记录信息。

ReadView

我们可以读取的记录数据对于不同的事务隔离级别是不同的。

[En]

The record data that we can read is different for different transaction isolation levels.

  • 对于尚未提交的隔离级别,我们可以直接读取最新版本的数据。
    [En]

    for isolation levels that have not been committed, we can read the latest version of the data directly.*

  • 对于提交读的隔离级别,我们需要读取的是已经提交的事务的修改数据。
    [En]

    for the isolation level of committed reads, what we need to read is the modification data of transactions that have been committed.*

  • 对于可重复隔离级别,我们需要能够读取事务启动前已提交的事务的数据。
    [En]

    for repeatable isolation levels, we need data that can read transactions that have been committed before the transaction starts.*

  • 对于串行读的隔离节别来说,Innodb采用加锁的方式来保证串行读。

对于中间两个隔离级别,就需要ReadView这个结构来实现MVCC。以下是ReadView的结构

  • m_ids : 表示在生成ReadView时当前系统中活跃的读写事务ID的列表
  • min_trx_id : 表示在生成ReadView时当前系统中活跃的读写事务ID的最小值即在m_ids中最小的事务ID。
  • max_trx_id : 表示生成ReadView时系统中应该分配给下一个事务的ID。
  • creator_trx_id : 表示生成该ReadView的事务ID。

有了ReadView这个结构,我们在就可以对事务进行控制。

  • 当被访问的记录行的事务ID大于等于max_trx_id,说明当前数据行不可见。
  • 当被访问的记录行的事务ID小于min_trx_id,可以直接获得数据。
  • 当被访问的记录行的事务ID等于creator_trx_id,说明是当前事务修改的记录,可以直接访问。
  • 当被访问的记录行的事务ID大于min_trx_id且小于max_trx_id,我们需要判断一下这个事务ID是不是在m_ids列表中,因为由可能是一个很早的事务很久还执行不介绍,导致中间的事务都结束了,如果在m_ids列表中,说明是活跃的,当前记录行不能访问,否则可以访问数据行。

当前情况从头到尾遍历版本链,直到获得数据。

[En]

The current situation traverses through the version chain from beginning to end until the data is obtained.

上面提到的提交读和可重复读,因为是两个隔离级别有区别的,两个隔离级别的实现只要在ReadView的时机上进行把控,就可以实现。

  • 提交读,我们只要保证当前事务的每个语句能读到已经提交的事务的数据。就可以在每个查询数据进行前,事务就会创建一个ReadView。
  • 可重复读,我们只要保证当前事务每个语句能读到事务开启前的数据,就可以在事务第一次读取数据时会创建ReadView,然后整个事务只会使用这个ReadView去判断能读取的数据行。

如果你仔细品尝,你会突然意识到这一点。

[En]

If you taste it carefully, you can suddenly realize it.

这个MVCC只会在我们使用普通select查询才会生效。

Original: https://www.cnblogs.com/duizhangz/p/16333589.html
Author: 大队长11
Title: MySQL之事务隔离级别和MVCC

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/505328/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MySQL之事务和redo日志

    事务 事务的四个ACID特性。 Atomicity 原子性 Consistency 一致性 Isolation 隔离性 Durability 持久性 原子性 原子性意味着事务的所有…

    数据库 2023年5月24日
    0154
  • 异常详解

    🦔异常 发现错误的理想时机是在编译阶段,也就是在运行程序之前。然而编译期间并不能找到所有的错误,余下的问题必须在运行期间解决。这就需要错误源能够通过某种方式,把适当的信息传递给某个…

    数据库 2023年6月14日
    0120
  • 给小白的 PostgreSQL 容器化部署教程(上)

    作者:王志斌编辑:钟华龙 本文来自社区小伙伴 王志斌 的投稿。从小白的角度,带你一步步实现将 RadonDB PostgreSQL 集群部署到 Kubernetes 上。文章分为上…

    数据库 2023年5月24日
    0150
  • 20 年老程序员告诉你的 20 条编码原则

    我从 1999 年就开始了编程生涯,到今年已经有 20 多年了。我先是从 Basic 开始,很快转到了 Pascal 和 C 语言,然后又学习了面向对象编程语言 Delphi 和 …

    数据库 2023年6月14日
    0144
  • Redis缓存相关的几个问题

    1 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来…

    数据库 2023年6月14日
    0136
  • SQLZOO练习7–Using NULL

    teacher表: iddeptnamephonemobile 101 1 Shrivell 2753 07986 555 1234 102 1 Throd 2754 07122 …

    数据库 2023年5月24日
    0129
  • docker 单机部署redis集群

    docker 部署redis集群 1、创建redis网卡 docker network create redis –subnet 172.38.0.0/16 查看网卡信息 doc…

    数据库 2023年6月11日
    0133
  • 图文实例解析,InnoDB 存储引擎中行锁的三种算法

    前文提到,对于 InnoDB 来说,随时都可以加锁(关于加锁的 SQL 语句这里就不说了,忘记的小伙伴可以翻一下上篇文章),但是并非随时都可以解锁。具体来说,InnoDB 采用的是…

    数据库 2023年6月6日
    0131
  • 23种设计模式之备忘录模式

    文章目录 概述 备忘录模式的优缺点 备忘录模式的结构和实现 * 模式结构 模式实现 总结 概述 备忘录模式(Memento Pattern) 保存一个对象的某个状态,以便在适当的时…

    数据库 2023年6月6日
    0127
  • 解决数据库报错Error 1390: Prepared statement contains too many placeholders的问题

    今天,当您开发一个项目时,您试图一次插入大量数据,但出现了以下错误: [En] Today, when you were developing a project, you tri…

    数据库 2023年5月24日
    0160
  • Java基础十—JavaIO

    CPU指令与内核态、用户态 在操作系统中,CPU负责执行指令,这些指令有些来自应用程序,有些是来自底层系统。有些指令是非常危险的,如清除内存,网络连接等等,如果错误调用的话有可能导…

    数据库 2023年6月6日
    0162
  • mysql 常用的命令2

    找出每个部门,不同工作岗位的最高薪资。 mysql> select deptno,job,max(sal) from emp group by deptno,job; +&#…

    数据库 2023年5月24日
    0115
  • 教师节我用Python做了个学生点名系统送给老师当礼物,这回毕业稳了

    今年教师节前夕,我特意用Python做了个学生点名系统,非常好用,送给各科老师、辅导员当节日礼物,老师们都喜滋滋,说平常逃课就原谅我了,我心想,这次毕业应该不是问题了~ 本文背景 …

    数据库 2023年6月14日
    0121
  • Windows安装mysql数据库

    一般我安装mysql用以下两个方法: 一.phpstudy环境下的mysql安装 只需将mysql的bin目录配置到系统环境变量即可, 输入默认密码root即可登录 二.本地直接安…

    数据库 2023年5月24日
    0142
  • python使用sys.path添加临时环境变量

    直接上代码: 1 # -*- coding: gbk -*- 2 import sys 3 4 sys.path.append(‘H:\project_py\jiJin’) # 把…

    数据库 2023年6月11日
    0132
  • SQL语句大全–SQL

    前言 本片博客使用mysql数据库进行数据操作,使用Navicat for mysql 这个IDE进行可视化操作。每个SQL语句都是亲身实验验证的,并且经过自己的思考的。能够保证s…

    数据库 2023年5月24日
    0100
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球