MYSQL数据库Innodb 引擎mvcc锁实现原理

MYSQL数据库Innodb 引擎mvcc锁实现原理

InnoDB是MySQL数据库的默认存储引擎,实现了被广泛使用的多版本并发控制(MVCC)锁机制,这使得InnoDB的并发处理能力比其他存储引擎更优秀。本文将重点讲解InnoDB的MVCC锁实现原理。

MVCC介绍

MVCC为多版本并发控制(Multi-Version Concurrency Control)的缩写。MVCC有时也称作Snapshot Isolation,即快照隔离级别。MVCC是为数据库并发控制而设计的,本质上是通过在每个事务中创建某个时间点的数据库快照来实现数据库隔离的。在已有的快照中读取可以避免由于读写同时存在而导致的资源竞争问题,这样就可以有效提高并发处理能力。

InnoDB的MVCC实现

在InnoDB的实现中,每一行记录都有多个版本。每个版本都有自己的版本号,这个版本号实际上由系统版本号(system version number)和事务编号(transaction ID)两个部分组成。其中,系统版本号是在之前任何一个事务操作InnoDB表时从磁盘读取的系统状态号,每当有事务提交时,状态号都会递增。事务编号是在每个事务开始时自动分配的。

当事务开始时,InnoDB会为每个事务分配一个唯一的事务编号,用于记录该事务对应的快照时间。InnoDB允许在一个事务中读取之前提交的数据快照,这样的查询也被称为快照读(Snapshot Read)。

在InnoDB的MVCC实现中,有两种类型的快照读:一种是一般性查询,另一种是当前读。现在将逐一介绍它们。

  1. 一般性查询(Non-Locking Read)

一般性查询是InnoDB的MVCC最基本的查询操作。它并不会加任何锁,也不会对其他事务带来任何阻塞。但它需要选择合适的版本号,根据版本号去快照中去读取数据。即使在同一事务中多次执行相同的查询,读取的数据结果也是不变的。

举个例子:一个表包含一条记录,记录的ID为1,当前有两个事务,分别为T1和T2:

在T1中,执行select * from table where id=1;

在T2中,执行update table set value='new value' where id=1;

那么在T1中,删除操作前,该表的记录快照是:(id=1, value=old value, sys version=1.1, trx id=T2)

在T1中,快照读会选择版本号1.1去获取该行记录,结果还是旧值old value。

  1. 当前读(Locking Read)

当前读会锁住一行记录,为查询之后的更新操作或删除操作创建MVCC多版本。执行当前读操作时,会获取行锁(Shared Lock、Exclusive Lock 以及Update Lock三种类型)来保证数据一致性。

在InnoDB中,行锁既可以由自动增加的事务id(auto-inc transaction id,即AIT)来生成。也可以是由事务直接指定的事务id来生成。事务可以通过事务隔离级别的设置来指定不同级别的行锁操作方式。

举个由当前读操作产生的示例:一个表包含一条记录,记录的ID为1,当前有两个事务,分别为T1和T2:

在T1中,执行select * from table where id=1 for update;

在T2中,执行update table set value='new value' where id=1;

那么在T1中,此时行锁会锁住记录ID为1的这一行,也因此可以通过当前读或当前写来解决并发问题。

总结

InnoDB的MVCC锁机制是实现并行执行的关键。通过对事务快照的创建,InnoDB保证了并发执行的正确性和完整性。同时,当前读操作可以对行记录进行锁定,保证同一事务中读取的数据版本是最新的。

示例1中,T1查询了表中ID为1的记录,因为是快照读,所以读取的数据是T1开启前提交的数据快照。示例2中,T1为了避免数据被其他事务更改,选择了行锁,锁定了表中ID为1的记录。这样在T2中执行更新操作时,将会等待T1事务完成释放锁才能执行。

以上是对InnoDB的MVCC锁实现原理的详细讲解。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:MYSQL数据库Innodb 引擎mvcc锁实现原理 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 简单了解C语言中主线程退出对子线程的影响

    了解 C 语言中主线程退出对子线程的影响,需要掌握以下知识点:多线程,同步和互斥机制,线程的生命周期等。 首先,我们需要了解一个线程的生命周期。一个线程的生命周期通常包含如下阶段:创建、就绪、运行、阻塞、终止。 在 C 语言中,我们通常使用 pthread_create() 函数来创建线程,使用 pthread_join() 函数来等待线程的终止,使用 pt…

    C 2023年5月22日
    00
  • C语言实现散列表(哈希Hash表)实例详解

    下面我将为您详细讲解“C语言实现散列表(哈希Hash表)实例详解”的完整攻略。 概述 哈希(Hash)是一种能够快速定位存储位置的技术。哈希表(Hash Table)也叫散列表,是利用哈希函数(Hash Function)进行访问的数据结构。C语言中的哈希表主要分为两种:开放地址法和链表法。 开放地址法又分为线性探测法、二次探测法和双重散列法。本文主要介绍使…

    C 2023年5月23日
    00
  • 详解关于JSON.parse()和JSON.stringify()的性能小测试

    关于“详解关于JSON.parse()和JSON.stringify()的性能小测试”攻略,以下是完整的说明: 标题 1. 概述 在JavaScript中,JSON.parse()和JSON.stringify()是两个常用的方法,前者将JSON格式的字符串转换为JavaScript对象,后者则是将JavaScript对象转换为JSON格式的字符串。同时,在…

    C 2023年5月23日
    00
  • C和C++的区别详解

    C和C++的区别详解 C和C++是两种非常常见的编程语言,在很多领域都有广泛的应用。虽然在某些方面它们很相似,但在许多方面它们也存在很大的差异。下面我们将详细说明C和C++之间的区别。 1. 语言的起源和发展历史 C语言是由Dennis Ritchie在20世纪70年代初创造的,最初是为了在Unix操作系统上编写系统级应用程序而设计的。C++语言则是由Bja…

    C 2023年5月22日
    00
  • 【c语言】整数拆分

    将一个正整数n拆分成若干个正整数的和(至少两个数,n<=100)。 输入格式: 一个正整数n 输出格式: 若干行,每行一个等式(数与数之间要求非降序排列)。最后一行给出解的总个数 输入样例: 在这里给出一组输入。例如: 4   输出样例: 4=1+1+1+1 4=1+1+2 4=1+3 4=2+2 4   最后一行的4表示总共有4个解。   主要思路:…

    C语言 2023年4月18日
    00
  • 利用gson将map转为json示例

    将Map类型转为JSON字符串,可以使用Google开源的Gson库。下面是将Map类型转换为JSON字符串的攻略: 引入Gson依赖 首先需要引入Gson库,在项目的build.gradle中添加如下依赖: dependencies { implementation ‘com.google.code.gson:gson:2.8.6’ } 使用Gson将Ma…

    C 2023年5月23日
    00
  • Mybatis-plus操作json字段实战教程

    下面是“Mybatis-plus操作json字段实战教程”的完整攻略: 1. 引入依赖 要操作json字段,我们需要引入fastjson依赖,以及mybatis-plus本身的依赖。在这里我们使用mybatis-plus的最新版本3.4.3: <dependency> <groupId>com.alibaba</groupId&…

    C 2023年5月23日
    00
  • 详解如何在VS2019和VScode中配置C++调用python接口

    下面就是在VS2019和VSCode中配置C++调用Python接口的详细攻略。本攻略包括以下步骤: 安装Python环境和相关库 配置VS2019的解决方案 配置VSCode 调用Python接口 示例说明 1. 安装Python环境和相关库 首先需要安装Python环境和相关库,以VS2019为例,需要下载安装以下软件: Python 3.x 安装包 (…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部