首页 > 数据库 >mysql 事务的隔离级别、MVCC

mysql 事务的隔离级别、MVCC

时间:2023-05-01 19:33:51浏览次数:46  
标签:事务 隔离 Read MVCC trx 读锁 mysql id

《凤凰架构》一书中对事务的隔离级别以及事务的定义很清晰

https://www.cnblogs.com/suBlog/p/16592859.html

总结

写锁:排他锁,其他事务不能写入数据,也不能施加读锁(可读,但是不可加读锁)

读锁:共享锁,多个事务可以同时施加读锁,但是其他事务不能写入数据

范围锁:不能修改范围内已有的数据,也不能对这个范围新增或删除数据

 

事务的隔离级别由高到低

可串行化:对所有读写数据的操作全部加上 写锁、读锁、范围锁

可重复读:只有读锁和写锁,但是没有范围锁。

问题:幻读--同一事务两个相同的查询范围得到了不同的结果。

因为更改了这个范围内的数据

读已提交:比起可重复读缺乏贯穿整个事务的读锁,select 后读锁立马释放了。

问题:不可重复读--同一事务对同一行数据的两次查询得到了不同的结果。

因为期间有事务2把这行数据改了,而事务1第一次读完读锁就释放了,使得事务2可以修改数据并提交了事务,事务1再读第二次时数据就变了。如果有贯穿整个事务的读锁的话,事务1两次都读完了,事务1提交后读锁释放 事务2才可以改数据,事务1两次读到的就是一样的。

读未提交:完全不加读锁

  问题:脏读--读到了另一个事务未提交的数据。

事务2更改了数据,事务还没提交,持有写锁。但是因为没有读锁,所以事务1可以读到这个被更改的加了写锁但还没提交的数据(加了写锁可读但不可加读锁)

 

事务是在 MySQL 引擎层实现的,我们常见的 InnoDB 引擎是支持事务的。InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?

  • 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。是通过 redo log (重做日志)来保证的;
  • 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完。通过 undo log(回滚日志) 来保证的;
  • 隔离性(Isolation):允许多个并发事务同时对其数据进行读写和修改的能力。 MVCC(多版本并发控制) 或锁机制来保证的;
  • 一致性(Consistency):是事务的目标,通过 持久性+原子性+隔离性 来保证;

不同的数据库厂商对 SQL 标准中规定的 4 种隔离级别的支持不一样,有的数据库只实现了其中几种隔离级别,我们讨论的 MySQL 虽然支持 4 种隔离级别,但是与SQL 标准中规定的各级隔离级别允许发生的现象却有些出入。

MySQL 在「可重复读」隔离级别下,可以很大程度上避免幻读现象的发生(注意是很大程度避免,并不是彻底避免),所以 MySQL 并不会使用「串行化」隔离级别来避免幻读现象的发生,因为使用「串行化」隔离级别会影响性能。

MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了,详见这篇文章 (opens new window)),解决的方案有两种:

  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

 

MVCC 是怎么样工作的?

以下是 Read View 中的四个字段

 

 

Read View 有四个重要的字段:

  • m_ids :指的是在创建 Read View 时当前数据库中「活跃事务」的事务 id 列表,注意是一个列表,“活跃事务”指的就是,启动了但还没提交的事务。
  • min_trx_id :指的是在创建 Read View 时,当前数据库中「活跃事务」中事务 id 最小的事务,也就是 m_ids 的最小值。
  • max_trx_id :这个并不是 m_ids 的最大值,而是创建 Read View 时当前数据库中应该给下一个事务的 id 值,也就是全局事务中最大的事务 id 值 + 1;
  • creator_trx_id :指的是创建该 Read View 的事务的事务 id。

 

聚簇索引记录中两个隐藏列

对于使用 InnoDB 存储引擎的数据库表,它的聚簇索引记录中都包含下面两个隐藏列:

  • trx_id,当一个事务对某条聚簇索引记录进行改动时,就会把该事务的事务 id 记录在 trx_id 隐藏列里(最新的已经提交了的事务id);
  • roll_pointer,每次对某条聚簇索引记录进行改动时,都会把旧版本的记录写入到 undo 日志中,然后这个隐藏列是个指针,指向每一个旧版本的版本链,于是就可以通过它找到修改前的记录。

在创建 Read View 后,我们可以将索引记录中的 trx_id 划分这三种情况:

一个事务去访问记录的时候,除了自己的更新记录总是可见之外,总结一下就是:

  • 索引记录上的当前版本在创建 readView 时已经提交事务,可见。将聚簇索引记录上的当前版本值 trx_id 与 readView 中的字段比,包括以下两种情况:
    1. 小于 min_trx_id 的
    2. 在 min_trx_id 和 max_trx_id 之间,但是不存在于 m_ids 之中的(不在创建 readView 时还活跃的事务中)
  • 索引记录上的当前版本在在创建 readView 时还没提交事务(或说活跃着),不可见;将聚簇索引记录上的当前版本值 trx_id 与 readView 中的字段比,包括以下两种情况:
    1. 大于 max_trx_id 的
    2. 在 min_trx_id 和 max_trx_id 之间,且存在于 m_ids 之中的(在创建 readView 时还活跃的事务中)

这种通过「版本链」来控制并发事务访问同一个记录时的行为就叫 MVCC(多版本并发控制)。

 

 

MVCC 怎样实现可重复读和读已提交隔离级别?

有锁化时它们的区别是 「读已提交」没有贯穿整个事务的读锁,而「可重复读」有。对于无锁化的 MVCC 实现(select 时是无锁的),就在于创建新 Read View 的时机不同:

  • 「读已提交」隔离级别是在每个 select 都会生成一个新的 Read View,也意味着,事务期间的多次读取同一条数据,前后两次读的数据可能会出现不一致,因为可能这期间另外一个事务修改了该记录,并提交了事务。
  • 「可重复读」隔离级别是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View,这样就保证了在事务期间读到的数据都是事务启动前的记录。

 

标签:事务,隔离,Read,MVCC,trx,读锁,mysql,id
From: https://www.cnblogs.com/suBlog/p/17366862.html

相关文章

  • mysql -- 存储过程
    存储过程如果需要在MySQL中执行一系列语句,可以将所有语句封装在单个程序中,并在需要的时候调用这个程序,而不是每次发送所有SQL语句。存储过程处理的是一组SQL语句,且没有返回值。除了SQL语句,还可以使用变量来存储结果并在存储过程中执行程序化的内容。例如可以使用if,case语句、......
  • 快速实现 MySQL 主从复制
    MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的二进制日志功能。就是一台或多台MySQL数据库(Slave库)从另一台MySQL数据库(master库)进行日志的复制,然后再解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无......
  • win10环境Windows环境下MYSQL5.7免安装版下载、配置(win10-x64位32g内存)
    win101-Windows环境下MYSQL5.7免安装版下载、配置(win10-x64位32g内存)  一、MYSQL免安装版下载二、解压安装三、设置登录、修改密码一、MYSQL免安装版下载1、下载链接:https://downloads.mysql.com/archives/community/.2、MySQL5.x版本以上需要收费,所以我选择了一个最新的(m......
  • MySql记录的一些使用方法和经验MariaDB
    MySql记录的一些使用方法和经验MariaDB MySQL数据库最初由瑞典的TomasUlin、AllanLarsson和MichaelWidenius创立。后来,该公司被SUNMicrosystems购买了,然后在2008年被Oracle购买。Oracle是一个主要提供商的商业数据库公司,这意味着MySQL现在是由Oracle控制并拥有的。然而,MyS......
  • MySQL Workbench和phpMyAdmin
    MySQLWorkbench是MySQL官方提供的一款开源的图形化管理工具,可以用于设计、开发、管理和维护MySQL数据库。MySQLWorkbench提供了一个集成开发环境(IDE),其中包含多个工具和功能,包括:1.数据建模工具:可以用于设计数据库模型、创建和编辑表、定义列、设置约束等。2.SQL编辑器:可以用......
  • MySQL基础命令 | ChatGPT问答记录
    问:MySQL基础命令ChatGPT:MySQL是一种流行的开源关系型数据库管理系统(RDBMS),以下是一些常见的MySQL基础命令:连接到MySQL服务器:mysql-uusername-ppassword-hhostname创建数据库:CREATEDATABASEdatabase_name;删除数据库:DROPDATABASEdatabase_name;选......
  • mysql几个主流版本介绍
    MySQL是一款非常流行的关系型数据库管理系统,历经多个版本。以下是MySQL的主流版本:MySQL5.7:该版本于2013年发布,包含了许多新特性和改进,如更好的性能、JSON支持、多源复制等。MySQL8.0:该版本于2018年发布,引入了原生JSON支持、更好地Unicode支持、解决云端部署时结构化数据需......
  • 制作一个包含Centos7+Nginx+Mysql8+JDK8的Docker镜像
    1.创建一个文件夹用于构建Docker镜像:mkdirmy-docker-imagecdmy-docker-image2.在该文件夹中创建一个名为Dockerfile的文件。vimDockerfile3.在Dockerfile中编写以下代码:FROMcentos:7#RUNsed-i's/deb.debian.org/mirrors.aliyun.com/g'/etc/apt/sources.list......
  • mysql -- 自带命令及工具
    ​ MySQL数据库不仅提供了数据库的服务器端应用程序,同时还提供了大量的客户端工具程序,如mysql、mysqladmin、mysqldump等等1.mysql命令mysql命令是使用最多的一个命令工具了,为用户提供一个命令行接口来操作管理MySQL服务器。mysql命令选项作用说明-u指定连接数据......
  • 使用docker快速安装mysql.md
    1.拉取mysql镜像dockerpullmysql:8.0.182.docker容器构建和运行mysqldockerrun--namemysql\ -p3306:3306\-eMYSQL_ROOT_PASSWORD=123456\ -v/home/mysql/data:/var/lib/mysql:rw\-v/home/mysql/mysql-files:/var/lib/mysql-files:rw\-v/home/......