【MySQL | 第九篇】重新认识MySQL锁

2024-05-01 10:28

本文主要是介绍【MySQL | 第九篇】重新认识MySQL锁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

文章目录

  • 9.重新认识MySQL锁
    • 9.1MySQL锁概述
    • 9.2锁分类
      • 9.2.1锁的粒度
      • 9.2.2锁的区间
      • 9.2.3锁的性能
      • 9.2.4锁的级别
    • 9.3拓展:意向锁
      • 9.3.1意向锁概述
      • 9.3.2意向锁分类
      • 9.3.3意向锁作用
        • (1)意向锁的兼容互斥性
        • (2)例子1(意向锁和表级的共享/排他锁互斥)
        • (3)例子2(意向锁和行级的共享锁/排他锁兼容)
        • (4)小结

9.重新认识MySQL锁

9.1MySQL锁概述

  • 锁是计算机协调多个进程或者线程并发访问某一资源的机制
  • 在数据库中除了传统的对计算资源的争抢之外,数据也是供许多用户共享的一种资源,如何保证多线程下的数据一致性是数据库必须解决的一个问题

9.2锁分类

共有四种角度将MySQL锁分类:

  • 锁的粒度:
    • 全局锁
    • 表级锁
    • 行级锁
    • 页级锁
  • 锁的区间:
    • 间隙锁
    • 临建锁
  • 锁的性能:
    • 乐观锁
    • 悲观锁
  • 锁的级别:
    • 共享锁(读锁)
    • 排他锁(写锁/独占锁)

9.2.1锁的粒度

  • 全局锁:锁住数据库中的所有表
  • 表级锁:锁住数据库中的整张表
  • 行级锁:锁住对应的行数据

9.2.2锁的区间

  • 间隙锁

    • 定义:间隙锁用于 锁定一个范围(开区间) 而不是单个行。当事务在范围内的一行上持有锁时,其他事务无法在这个范围内插入新的数据,但是可以在范围之外插入新的数据。
    • 举例:假设一个表中的索引列有序且不重复,事务A持有了某个范围内的间隙锁,这个范围可能是一段索引范围,比如(10,20),这时其他事务无法在这个范围内插入新的行。
  • 临建锁

    • 定义::临建锁是一种结合了行锁和间隙锁的锁类型,它在锁定一个范围时同时锁定了该范围内的行以及范围之间的间隙
    • 举例:考虑一个范围查询,比如查询索引列值在(10,20)之间的行,临建锁会锁定这个范围内的行,同时锁定范围之间的间隙,防止其他事务在这个范围内插入新的行或者改变已有行的值。

9.2.3锁的性能

  • 乐观锁:

    • 定义:乐观锁认为数据在被操作时很少发生冲突,因此在访问数据时不会立即加锁,而是在更新数据时检查数据是否被其他事务修改过,如果没有则更新成功,否则进行回滚或者重试。

    • 举例:在MySQL中,可以使用乐观锁的方式是在更新数据时检查数据的版本号或者时间戳是否与当前操作一致

      UPDATE table_name 
      SET column1 = value1, version = new_version WHERE id = x AND version = old_version;
      
  • 悲观锁:

    • 定义:悲观锁认为数据在被操作时会发生冲突,因此在访问数据之前会先加锁,确保其他事务无法修改该数据,直到当前事务完成操作并释放锁。

    • 举例:在MySQL中,可以使用SELECT … FOR UPDATE语句来获取悲观锁,例如

      SELECT * 
      FROM table_name 
      WHERE condition 
      FOR UPDATE;
      

9.2.4锁的级别

  • 共享锁:

    • 定义:共享锁允许多个事务同时读取同一行数据,但阻止其他事务在该行上获取排他锁;

    • 举例:在 MySQL 中,可以使用 SELECT ... LOCK IN SHARE MODE 或者 SELECT ... FOR SHARE 来获取共享锁,例如

      SELECT * 
      FROM table_name 
      WHERE condition 
      LOCK IN SHARE MODE;
      
  • 排他锁:

    • 定义:排他锁(也称为写锁)阻止其他事务对同一行数据进行读取或写入操作,只有获取了排他锁的事务才能对数据进行修改

    • 举例:在 MySQL 中,可以使用 SELECT ... FOR UPDATE 来获取排他锁,例如

      SELECT * 
      FROM table_name 
      WHERE condition 
      FOR UPDATE;
      

9.3拓展:意向锁

9.3.1意向锁概述

MySQL 中的意向锁(Intention Lock)是一种用于管理表级锁的锁机制,用于在表级别上指示事务将要在表的哪些行上获取锁

意向锁并不是实际的锁,而是一种指示,通常用于协调事务对表级锁的获取,以提高并发性能和降低死锁的风险。

9.3.2意向锁分类

可分为两种类型:意向共享锁和意向排他锁

  • 意向共享锁(Intention Share Lock):

    • 特点:表明事务将要在表的某些行上获取共享锁。当一个事务打算获取某行的共享锁时,会在表级别请求意向共享锁
    • 作用:意向共享锁是为了协调多个事务同时获取共享锁而引入的,在获取共享锁之前,需要先检查是否存在排他锁,以防止与其他事务的排他锁冲突
  • 意向排他锁(Intention Exclusive Lock):

    • 特点:表明事务将要在表的某些行上获取排他锁。当一个事务打算获取某行的排他锁时,会在表级别请求意向排他锁
    • 作用:意向排他锁是为了协调多个事务同时获取排他锁而引入的,在获取排他锁之前,需要先检查是否存在共享锁或其他事务的排他锁,以防止与其他事务的共享锁或排他锁冲突

9.3.3意向锁作用

没有意向锁时,事务在获取表级锁/行级锁之前可能需要频繁地检查整个表,以确定是否有其他事务已经持有了排他锁或共享锁。这会增加系统的开销,降低并发性能。

举例:

事务 A 获取了某一行的排他锁,并未提交:

SELECT * FROM users WHERE id = 6 FOR UPDATE;

事务 B 想要获取 users 表的表锁(共享锁)/行级锁:

LOCK TABLES users READ;

为共享锁与排他锁互斥,所以事务 B 在视图对 users 表加共享锁的时候,必须保证:

  • 当前没有其他事务持有 users 表的排他锁。
  • 当前没有其他事务持有 users 表中任意一行的排他锁

为了检测是否满足第二个条件,事务 B 必须在确保 users表不存在任何排他锁的前提下,去检测表中的每一行是否存在排他锁

很明显这是一个效率很差的做法,但是有了意向锁之后,情况就不一样了:

(1)意向锁的兼容互斥性

特点:多个事务可以对同一张表多个意向排他锁

意向共享锁(IS)意向排他锁(IX)
意向共享锁(IS)兼容兼容
意向排他锁(IX)兼容兼容

意向锁之间是互相兼容的,虽然意向锁和自家兄弟互相兼容,但是它会与普通的排他 / 共享锁互斥

意向共享锁(IS)意向排他锁(IX)
共享锁(S)兼容互斥
排他锁(X)互斥互斥

注意:这里的排他 / 共享锁指的都是表锁!!!

意向锁不会与行级的共享 / 排他锁互斥!!!

(2)例子1(意向锁和表级的共享/排他锁互斥)

回到刚才 users 表的例子:

事务 A 获取了某一行的排他锁,并未提交:

SELECT * FROM users WHERE id = 6 FOR UPDATE;
  • 此时 users 表存在两把锁:users 表上的意向排他锁与 id 为 6 的数据行上的排他锁

事务 B 想要获取 users 表的表锁(共享锁):

LOCK TABLES users READ;
  • 此时事务 B 检测事务 A 持有 users 表的意向排他锁,就可以得知事务 A 必然持有该表中某些数据行的排他锁
  • 事务 Busers 表的加锁请求就会被排斥(阻塞),而无需去检测表中的每一行数据是否存在排他锁
(3)例子2(意向锁和行级的共享锁/排他锁兼容)
  • 意向锁并不会影响到多个事务对不同数据行加排他锁时的并发性

事务 A 获取了某一行的排他锁,并未提交:

SELECT * FROM users WHERE id = 6 FOR UPDATE;
  • 此时 users 表存在两把锁:
    • users 表上的意向排他锁
    • id 为 6 的数据行上的排他锁

事务 B 想要获取 users 表的表锁(共享锁):

LOCK TABLES users READ;
  • 此时事务 B 检测事务 A 持有 users 表的意向排他锁,就可以得知事务 A 必然持有该表中某些数据行的排他锁
  • 事务 Busers 表的加锁请求就会被排斥(阻塞),而无需去检测表中的每一行数据是否存在排他锁

最后事务 C 也想获取 users 表中某一行的排他锁

SELECT * FROM users WHERE id = 5 FOR UPDATE;
  1. 事务 C 申请 users 表的意向排他锁
  2. 事务 C 检测到事务 A 持有 users 表的意向排他锁
  3. 因为意向锁之间并不互斥,所以 事务 C 获取到了 users 表的意向排他锁
  4. 因为id 为 5 的数据行上不存在任何排他锁,最终事务 C 成功获取到了该数据行上的排他锁
(4)小结

意向锁的引入主要是为了提高并发性能。通过引入意向锁,MySQL 可以更有效地管理表级锁,减少了在并发环境下的锁冲突,从而提高了系统的并发处理能力。

在没有意向锁之前,如果一张表里面已经有行锁了此时我们再添加表锁,为了防止表锁和行锁发生冲突,表锁就需要遍历整个表中的数据检查是否有行锁。为了优化表锁检索行锁的过程,我们引入意向锁。

在这里插入图片描述

这篇关于【MySQL | 第九篇】重新认识MySQL锁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/951447

相关文章

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

MySQL错误代码2058和2059的解决办法

《MySQL错误代码2058和2059的解决办法》:本文主要介绍MySQL错误代码2058和2059的解决办法,2058和2059的错误码核心都是你用的客户端工具和mysql版本的密码插件不匹配,... 目录1. 前置理解2.报错现象3.解决办法(敲重点!!!)1. php前置理解2058和2059的错误

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

MySQL Workbench 安装教程(保姆级)

《MySQLWorkbench安装教程(保姆级)》MySQLWorkbench是一款强大的数据库设计和管理工具,本文主要介绍了MySQLWorkbench安装教程,文中通过图文介绍的非常详细,对大... 目录前言:详细步骤:一、检查安装的数据库版本二、在官网下载对应的mysql Workbench版本,要是

mysql数据库重置表主键id的实现

《mysql数据库重置表主键id的实现》在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,本文主要介绍了mysql数据库重置表主键id的实现,具有一定的参考价值,感兴趣的可以了... 目录关键语法演示案例在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,当我们