InnoDB锁介绍

本文主要介绍MySQL InnoDB引擎中的各种锁策略和锁类别,并针对记录锁做演示以便于理解。

以下内容适用于MySQL 8.0版本。

读写锁

处理并发读/写访问的系统通常实现一个由两种锁类型组成的锁系统。这两种锁通常被称为共享锁(shared lock)和排他锁(exclusive lock),也叫读锁(read lock)和写锁(write lock)。

读锁

资源上的读锁是共享的,或者说是相互不阻塞的。多个客户端可以同时读取同一个资源而互不干扰。

写锁

写锁则是排他的,也就是说,一个写锁既会阻塞读锁也会阻塞其他的写锁,这是出于安全策略的考虑,只有这样才能确保在特定的时间点只有一个客户端能执行写入,并防止其他客户端读取正在写入的资源。

锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。尽量只锁定包含需要修改的部分数据,而不是所有的资源。但是锁的范围越小,管理锁的逻辑就会越复杂,开销也越大。因此锁定策略是锁开销和数据安全性之间的平衡,这种平衡会影响性能。MySQL提供了两种粒度的锁。

表锁

InnoDB的表级别锁包含五种锁模式:LOCK_IS、LOCK_IX、LOCK_X、LOCK_S以及LOCK_AUTO_INC锁。

LOCK_IS/LOCK_IX

也就是所谓的意向锁,这实际上可以理解为一种“暗示”未来需要什么样行级锁,IS表示未来可能需要在这个表的某些记录上加共享锁,IX表示未来可能需要在这个表的某些记录上加排他锁。意向锁是表级别的,IS和IX锁之间相互并不冲突,但与表级S/X锁冲突。

在对记录加S锁或者X锁时,必须保证其在相同的表上有对应的意向锁或者锁强度更高的表级锁。

LOCK_X

当加了LOCK_X表级锁时,所有其他的表级锁请求都需要等待。X锁的几个情况:

  • DDL操作的最后一个阶段(ha_innobase::commit_inlace_alter_table)对表上加LOCK_X锁,以确保没有别的事务持有表级锁。通常情况下Server层MDL锁已经能保证这一点了,在DDL的commit 阶段是加了排他的MDL锁的。但诸如外键检查或者刚从崩溃恢复的事务正在进行某些操作,这些操作都是直接InnoDB自治的,不走server层,也就无法通过MDL所保护;

  • 当设置会话的autocommit变量为OFF时,执行LOCK TABLE tbname WRITE这样的操作会加表级的LOCK_X锁(ha_innobase::external_lock);

  • 对某个表空间执行discard或者import操作时,需要加LOCK_X锁(ha_innobase::discard_or_import_tablespace)。

LOCK_S
  • 在DDL的第一个阶段,如果当前DDL不能通过ONLINE的方式执行,则对表加LOCK_S锁(prepare_inplace_alter_table_dict);

  • 设置会话的autocommit为OFF,执行LOCK TABLE tbname READ时,会加LOCK_S锁(ha_innobase::external_lock)。

当客户端想对表进行写操作(插入、删除、更新等)时,需要先获得一个写锁,这会阻塞其他客户端对该表的所有读写操作。只有没有人执行写操作时,其他读取的客户端才能获得读锁,读锁之间不会相互阻塞。

表锁的冲突和兼容情况

XIXSIS
XConflictConflictConflictConflict
IXConflictCompatibleConflictCompatible
SConflictConflictCompatibleCompatible
ISConflictCompatibleCompatibleCompatible

从上面的描述我们可以看到LOCK_X及LOCK_S锁在实际的大部分负载中都很少会遇到。主要还是互相不冲突的LOCK_IS及LOCK_IX锁。一个有趣的问题是,每次加表锁时,却总是要扫描表上所有的表级锁对象,检查是否有冲突的锁。很显然,如果我们在同一张表上的更新并发度很高,这个链表就会非常长。

基于大多数表锁不冲突的事实,我们在RDS MYSQL中对各种表锁对象进行计数,在检查是否有冲突时,例如当前申请的是意向锁,如果此时LOCK_S和LOCK_X的锁计数都是0,就可以认为没有冲突,直接忽略检查。由于检查是在持有全局大锁lock_sys->mutex下进行的。在单表大并发下,这个优化的效果还是非常明显的,可以减少持有全局大锁的时间。

LOCK_AUTO_INC

AUTO_INC锁加在表级别,和AUTO_INC、表级S锁以及X锁不相容。锁的范围为SQL级别,SQL结束后即释放。

行锁

使用行级锁(row lock)可以最大程度地支持并发处理(也带来了最大的锁开销)。行级锁是在存储引擎而不是服务器中实现的。行锁依赖索引加锁,如果表没有索引,InnoDB会将锁加在隐藏的聚簇索引上。

Record Locks(行记录锁)

表示这个锁对象只是单纯的锁在记录上,不会锁记录之前的 GAP。比如利用唯一索引查询表中存在的一条记录。

Gap Locks(间隙锁)

间隙锁,锁定一个范围,但不包含这个范围中的行记录。

Next-Key Locks

上面两种锁的结合,锁定一个范围和这个范围内的行记录本身。目标是解决幻读问题(Phantom Problem)。

Record Locks演示

表结构

CREATE TABLE `tx_demo` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `age` int DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_age` (`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

数据

id

age

name

15

5

agc

16

8

agc

17

12

agc

19

13

agc

行记录锁演示

  1. 开始事务后执行SQL

    -- 开始事务后执行SQL
    select * from tx_demo where id = 19 for update;
  2. 查看持有锁的情况

    -- 查看持有锁的情况
    SELECT 
        thread_id,
        INDEX_NAME,
        LOCK_TYPE,
        LOCK_MODE,
        LOCK_STATUS,
        LOCK_DATA
    FROM
        performance_schema.data_locks;

  3. 持有锁的情况 

如上所示,该事务当前持有的锁是索引记录19,LOCK_MODE是X,REC_NOT_GAP。原因是该索引是唯一索引,并且该查询能检索出唯一一条数据。

Gap Locks演示
  1. 开始事务后执行SQL

    -- 开始事务后执行SQL
    select * from tx_demo where age = 10 for update;
  2. 查看持有锁的情况

    -- 查看持有锁的情况
    SELECT 
        thread_id,
        INDEX_NAME,
        LOCK_TYPE,
        LOCK_MODE,
        LOCK_STATUS,
        LOCK_DATA
    FROM
        performance_schema.data_locks;
  3. 持有锁的情况

 

如上所示,因为表中没有age=10的记录,因此Gap Locks锁定了(8,12)这个区间,注意,不包括12个索引记录。

Next-Key Locks演示
  1. 开始事务后执行SQL

    -- 开始事务后执行SQL
    select * from tx_demo where age = 8 for update;

  2. 查看持有锁的情况
    -- 查看持有锁的情况
    SELECT 
        thread_id,
        INDEX_NAME,
        LOCK_TYPE,
        LOCK_MODE,
        LOCK_STATUS,
        LOCK_DATA
    FROM
        performance_schema.data_locks;
  3. 持有锁的情况

 

如上所示,在索引idx_age上,这里涉及到的Record Locks是索引记录8,涉及到的Gap Locks有两个,分别是(5,8)、(8,12),因此结合起来就是Next-Key Locks (5,8]和Gap Locks(8,12)。 表中Next-Key Locks (5,8]的表示就是LOCK_DATA为8,16那一行,LOCK_MODE是X;表中Gap Locks(8,12)的表示就是LOCK_DATA为12,17那一行,LOCK_MODE是X,REC_NOT_GAP

LOCK_MODE的含义

MySQL表performance_schema.data_locks中LOCK_MODE列的含义

  • LOCK_MODE = X,说明是 X 型的 next-key 锁;

  • LOCK_MODE = X, REC_NOT_GAP,说明是 X 型的记录锁;

  • LOCK_MODE = X, GAP,说明是 X 型的间隙锁;

  • LOCK_MODE = AUTO_INC,说明是表级自增锁;

  • LOCK_MODE = UNKNOWN,说明是未知模式锁;

参考文档

https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html

https://dev.mysql.com/doc/refman/8.0/en/performance-schema-data-locks-table.html

https://xiaolincoding.com/mysql/lock/show_lock.html#%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C

http://mysql.taobao.org/monthly/2016/01/01/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/417418.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java玩转《啊哈算法》暴力枚举之坑爹奥数

每个笨蛋都会随时准备杀了自己,这是最怯懦,也是最简单的出路。 路 缘起代码地址枚举题1题2题2 - Plus完整代码 缘起 各位小伙伴们好呀!本人最近看了下《啊哈算法》,写的确实不错。 但稍显遗憾的是,书籍示例代码是c语…

算法修炼-动态规划之斐波那契数列模型

一、动态规划的算法原理 这是本人动态规划的第一篇文章,所以先阐述一下动态规划的算法原理以及做题步骤。动态规划本人的理解就是通过题目所给的条件正确地填满dp表(一段数组)。首先要先确定好dp表每个位置的值所代表的含义是什么&#xff0c…

二叉树的增删查改

本节复习二叉树的增删查改, 二叉树的知识相对于前面的循序表, 链表, 以及栈和队列都要多一些。 同时二叉树的增删查改理解起来相对来说要困难一些。 本节来好好复习一下二叉树的增删查改。 目录 准备文件 创建结构体蓝图 二叉树的前序遍历…

Windows PowerShell 命令行历史记录补全

Windows 命令行历史记录补全 使用 powershell 安装PSReadLine 2.1.0 Install-Module PSReadLine -RequiredVersion 2.1.0检查是否存在配置文件 Test-path $profile # 为 false 则执行命令创建 New-item –type file –force $profile编辑配置文件 notepad $profile# 输入如下…

数据结构------栈(Stack)和队列(Queue)

也是好久没写博客了,那今天就回归一下,写一篇数据结构的博客吧。今天要写的是栈和队列,也是数据结构中比较基础的知识。那么下面开始今天要写的博客了。 目录 栈(Stack) 队列(Queue) 喜欢就点…

从C到C++

二、从C到C 本章介绍一些C拓展的非面向对象功能。 引用&#xff08;掌握&#xff09; 1.1 概念 引用从一定程度上讲是一个指针的平替&#xff0c;几乎被所有面向对象编程语言所使用。引用相当于对某一个目标变量起”别名“。 操作引用与操作原变量完全一样。 #include <iost…

工厂模式 详解 设计模式

工厂模式 其主要目的是封装对象的创建过程&#xff0c;使客户端代码和具体的对象实现解耦。这样子就不用每次都new对象&#xff0c;更换对象的话&#xff0c;所有new对象的地方也要修改&#xff0c;违背了开闭原则&#xff08;对扩展开放&#xff0c;对修改关闭&#xff09;。…

Unity UI适配规则和对热门游戏适配策略的拆解

前言 本文会介绍一些关于UI适配的基础概念&#xff0c;并且统计了市面上常见的设备的分辨率的情况。同时通过拆解目前市面上较为成功的两款休闲游戏Royal Match和Monopoly GO(两款均为近期游戏付费榜前几的游戏)&#xff0c;大致推断出他们的适配策略&#xff0c;以供学习和参…

go并发模式之----阻塞/屏障模式

常见模式之一&#xff1a;阻塞/屏障模式 定义 顾名思义&#xff0c;就是阻塞等待所有goroutine&#xff0c;直到所有goroutine完成&#xff0c;聚合所有结果 使用场景 多个网络请求&#xff0c;聚合结果 大任务拆分成多个子任务&#xff0c;聚合结果 示例 package main ​…

Delegate动画案例(P30 5.6delegate动画)

一、ListElement&#xff0c;ListModel&#xff0c;ListView 1. ListElement ListElement 是 QML 中用于定义列表项的元素。它可以包含多个属性&#xff0c;每个属性对应列表项中的一个数据字段。通过在 ListModel 中使用 ListElement&#xff0c;可以定义一个列表的数据模型…

USB-C接口:办公新宠,一线连接笔记本与显示器

USB-C接口如今已成为笔记本与显示器连接的优选方案。无需担心正反插错&#xff0c;支持雷电4和DP视频信号输出&#xff0c;高速数据传输&#xff0c;还有最高100W的快充功能&#xff0c;真是方便又实用&#xff01; 一线连接&#xff0c;多功能融合 通过这个接口&#xff0c;你…

面试笔记系列三之spring基础知识点整理及常见面试题

目录 如何实现一个IOC容器? 说说你对Spring 的理解&#xff1f; 你觉得Spring的核心是什么&#xff1f; 说一下使用spring的优势&#xff1f; Spring是如何简化开发的&#xff1f; IOC 运行时序 prepareRefresh() 初始化上下文环境 obtainFreshBeanFactory() 创建并…

瑞_23种设计模式_外观模式

文章目录 1 外观模式&#xff08;Facade Pattern&#xff09;1.1 介绍1.2 概述1.3 外观模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 jdk源码解析 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《23种设计模式》的外观模式篇。本文中的部分…

如何在Windows部署TortoiseSVN客户端并实现公网连接内网VisualSVN服务端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

Flutter开发之Slider

Flutter开发之Slider 本文是关于介绍Slider相关属性的含义。 class SliderThemeData {/// slider轨道的高度 final double? trackHeight; /// 滑块滑过的轨道颜色 final Color? activeTrackColor; /// 滑块未滑过的轨道颜色 final Color? inactiveTrackColor; /// 滑块滑过…

JavaEE——简单认识JavaScript

文章目录 一、简单认识 JavaScript 的组成二、基本的输入输出和简单语法三、变量的使用四、JS 中的动态类型图示解释常见语言的类型形式 五、JS中的数组六、JS 中的函数七、JS 中的对象 一、简单认识 JavaScript 的组成 对于 JavaScript &#xff0c;其中的组成大致分为下面的…

多线程如何设计?一对多/多对一/多对多

二、14个多线程设计模式 参考原文&#xff1a;https://www.cnblogs.com/rainbowbridge/p/17443503.html single Thread 模式 一座桥只能通过一个人 Single Thread模式是一种单线程设计模式&#xff0c;即在一个应用程序中只有一个主线程、一个事件循环&#xff0c;对外只提…

【C语言基础】:深入理解指针(一)

文章目录 一、内存和地址1. 内存2. 如何理解编址 二、指针变量和地址2.1 取地址操作符(&)2.2 指针变量和解引用操作符(*)2.2.1 指针变量2.2.2 如何拆解指针变量2.2.3 解引用操作符 2.3 指针变量的大小 三、指针变量类型的意义3.1 指针的解引用3.2 指针 - 整数3.3 void*指针…

什么是物联网?

今天这篇文章写的相关内容就是带领大家了解什么是物联网&#xff0c;之前写的文章大多都是一些物联网的未来&#xff0c;行业的解决方案等&#xff1b;话不多说开始进入正题吧! 物联网(IoT)是一个包罗万象的术语&#xff0c;指的是越来越多的电子产品&#xff0c;它们不是传统的…

vue2+elementui上传照片(el-upload 超简单)

文章目录 element上传附件&#xff08;el-upload 超详细&#xff09;代码展示html代码data中methods中接口写法 总结 element上传附件&#xff08;el-upload 超详细&#xff09; 这个功能其实比较常见的功能&#xff0c;后台管理系统基本上都有&#xff0c;这就离不开element的…