一、简介

  锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除了传统的计算资源(CPU、RAM、i/O)的挣用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素,从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

二、分类

  MySQL中的锁、按照锁的粒度分,分为以下三类

  • 全局锁:锁定数据量的所有表
  • 表级锁:每次操作锁住整张表
  • 行级锁:每次操作锁住对应的行数据

三、全局锁

  3.1 简介

    全局锁就是对整个数据库实例枷锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,以及更新操作的事物提交语句都会被阻塞,其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

  3.2 添加全局锁语法

flush tables with read lock;

  3.3 打开全局锁语法

unlock tables;

  3.4 案例一

  

    说明1:客户端1中设置了全局锁

    说明2:客户端2中,执行查询语句正常的,但是执行DML语句中的更新操作却是处于阻塞状态

  3.5 案例二

  

    说明1:客户端1中设置了全局锁

    说明2:客户端3中做了数据库备份的语句,其中mysqldump是和mysql一样由MySQL服务器提供的数据库备份的命令

    说明3:当数据库设置了全局锁的时候,不影响数据库的备份

    说明4:MySQL备份实在终端命令行模式下,不是在数据库命令模式下,注意!注意!注意!

  3.6 案例三

  

    说明1:客户端1释放全局锁

    说明2:客户端2的更新语句马上执行成功

    说明3:通过客户端2的更新语句的执行时间37min,可以说明该语句被客户端1的全局锁,阻塞了37分钟

  3.7 全局锁特点

    数据库中加全局锁,是一个比较重的操作,存在以下问题

    • 如果在主库上备份,那么在备份期间都不能执行更新,业务上基本就是停摆状态
    • 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟

    在innoDB引擎中,我们可以在备份时加上 --single-transaction 参数来完成不加锁的一致性数据备份

四、表级锁

  4.1 简介

    表级锁,每次操作锁住整张表,锁定粒度大,发生锁冲突的概率最高,并发度最低,应用在MyISAM,InnoDB等存储引擎中

  4.2 表级锁的分类

    • 表锁
    • 元数据锁(meta data lock, MDL)
    • 意向锁

五、表锁

  5.1 表锁的分类

    • 表共享读锁(read lock)
    • 表独占写锁(write lock)

  5.2 表锁语法

    加锁:lock tables 表名... read/write

    释放锁:unlock tables / 客户端断开连接

    说明1:加锁的时候,可以多张表同时加锁

    说明2:客户端断开连接也能释放表锁

  5.3 读锁案例

    

   

     说明1:当对一个表添加读锁,不会影响其读取数据,但是会影响其新增,修改,删除的操作语句

    说明2:当对一个表添加读锁,不会影响其他客户端读取数据,但是会让其他客户端的新增,修改,删除等操作语句处于阻塞状态。

    说明3:当把锁释放了,自己及其他客户端的新增,删除和修改语句才会结束阻塞。

  5.4 写锁案例

    

    

    说明1:添加写锁的客户端可以正常对表进行查询和增删改等操作

    说明2:其他客户端的查询,修改,新增,删除都操作在有写锁的情况下,都要处于阻塞状态,直到其添加写锁的客户端释放写锁。

    说明3:上图中的修改等应该是DML语句(Data Manipulation Language 数据操作语言,用来对数据库表中的数据进行增删改的),不是DDL语句(DDL: Data Definition Language 数据定义语言,用来定义数据库对象,数据库,表,字段)

六、元数据锁

  6.1 元数据锁简介:

    元数据锁(meta data lock):简称 MDL

    MDL加锁过程是系统自动控制,无需显示使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作,为了避免DML和DDL冲突,保证读写的正确性

  6.2 元数据锁的类型

    在MySQL5.5 中引入了MDL, 当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)

    

  6.3 案例

    

    说明1:select 和 update 分别会添加SHARED_READ 和 SHARED_WRITE, 但是SHARED_READ 和 SHARED_WRITE是兼容的,所以其他客户端是可以做更删改查的

    

    说明2:alter table 会产生EXCLUSIVE 锁。该锁与其他MDL都互斥。ß

  6.4 查看元数据锁

select object_type,object_schema,object_name,lock_type,locak_duration from  performance_schema.metadata_locks;

    

七、意向锁

  7.1 意向锁介绍

    为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每一行数据是否加锁,使用意向锁来减少表锁的检查。

    情况1:不加意向锁

   

    说明1:线程A 开启一个事务,并且使用DML语句更新数据,此时会对更新的数据添加行锁,

    说明2:此时线程A 的事务并没有提交事务,线程B又对该表添加一个表锁,此时添加表锁的时候,就会从第一条数据,依次检查到最后一条数据,看是否有其他的锁,如果有其他锁,需要等到其他锁释放了,才能执行添加表锁

    说明3:此时添加表锁的效率就非常低  

    情况2:加意向锁

   

    说明4:当线程A 开启了一个事务,并且执行了DML的更新数据的语句,此时除了会给该行数据添加行锁之外,还会添加一个基于整表的意向锁。

    说明5:当线程B 再次添加表锁的时候,就不用逐行排查是否有行锁了,而是直接检查整表是否有意向锁,如果意向锁和表锁兼容则直接加表锁

    说明6:如果表锁和意向锁不兼容,则仍然会等到意向锁释放了,表锁才能添加成功。

  7.2 意向锁的类型

    • 意向共享锁(IS): 由语句 select ... lock in share mode 添加。与表锁共享锁(read)兼容,与表锁排它锁(write)互斥。
    • 意向排它锁(IX): 由 insert, update, delete, select ... for update 添加。  与表锁共享锁(read)及排它锁(write)都互斥,意向锁之间不会互斥

  7.3 意向锁查询

select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks;

  7.4 意向锁案例

    

    说明1:客户端1开启事务,并且查询语句时设置一个意向共享锁(IS)

    说明2:客户端2在客户端1的事务未提交的时候,创建read锁成功

    说明3:意向共享锁(IS)和read共享锁兼容

    

    说明4:执行update等DML语句时,MySQL会自动添加行锁和排他意向锁。

    

    说明5:排他意向锁与共享read锁和排他write锁都互斥

    说明6:意向锁的作用主要是解决行锁和表锁之间的矛盾。

八、行级锁

  8.1、简介

    行级锁,每次操作锁住对应的行数据,所得粒度最小,发生锁冲突的概率最低,并发度最高,应用在InnoDB存储引擎中

    InnoDB的数据是基于索引组织的行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁,对于行级锁,主要分为一下三类

    1、行锁(record lock): 锁定单个行记录的锁,防止其他事务对此行进行update和delete,在read committed和repeatable read隔离级别下都支持。

    

    2、间隙锁(Gap lock): 锁定索引记录间隙(不包含记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读,在repeatable read隔离级别下支持

     

    3、临建锁(Next-Key lock): 行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙,在repeatable read隔离级别下支持

     

  8.2 行锁

    InnoDB 实现了一下两种类型的行锁

    1、共享锁(S): 允许一个事物去读一行,阻止其他事务获得相同数据集的排他锁。

    2、排他锁(X): 允许获取排他锁的事务更新数据,阻止其他事物获得相同数据集的共享锁和排他锁

    

    3、不同语句的枷锁情况

    

    4、默认情况下,InnoDB在 repeatable read隔离级别下运行,InnoDB使用next-key锁进行行搜索和索引扫描,以防止幻读

    • 针对唯一索引进行检索时,对已经存在的记录进行等值匹配时,将会自动优化为行锁
    • InnoDB的行锁是针对于索引加的锁,不通过索引检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁

   8.3 行锁案例

    

    说明1:客户端1开始事务,并执行查询语句,客户端2锁的情况,显示为空表

    说明2:客户端执行查询语句,并手动添加共享,在客户端2中,查询lock_mode字段中有一个S,即共享锁:

    

    说明3:客户端2也手动开启了一个共享锁,并且成功,说明共享锁与共享锁之间是兼容的。

    

    说明5:在客户端2上执行更新id=2的数据成功,并且查询可以看出,自动增加了一个(X)排它锁。

    说明6:  因为更新id=2的数据时,id=2的这一行上没有其他的锁,所以可以执行成功

    说明7:因为在客户点1上已经对id=1的行上添加了一个共享锁(S), 这是客户端2对id=1的数据做update操作时会自动在id=1的数据上在添加一个排它锁(X),这是id=1的数据上就会有共享锁(S)和排它锁(X),又因为共享锁和排它锁不兼容,所以在update id = 1 的时候就会阻塞,需要等到共享锁(S)释放了,才能执行成功。

    

   说明8:排它锁X 与 排它锁X 也是不兼容的。

    

    说明9:InnoDB的行锁是针对于索引加的锁,不通过索引检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁

    

    说明10:根据业务需要,尽量使用索引当所查询条件,既快又减少阻塞。

九、间隙锁/临建锁

  9.1 默认情况下、InnoDB在 repeatable read 事务隔离级别运行,InnoDB使用next-key 锁进行搜索和索引扫描,以防止幻读。

    

  9.2 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁

    

  9.3 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁

    

    说明1:非唯一索引,即普通索引,在做等值查询的时候,会添加三把锁

    说明2:在查询的当条记录上添加一个共享锁,允许其他事务继续查询该记录

    说明3:通过标注6的位置,lock_type 为S,REC_NOT_GAP 说明同时给这一行添加一个行锁

    说明4:通过标注7的位置,lock_type 为 S,GAP 说明在第一个不满足查询数据的前面也会加一个间隙锁。其目的是为了防止在select 查询的时候,其他事务去往这个索引之前插入或者修改数据,这样查询就会出现幻读的现象。

  9.4 索引上的范围查询(唯一索引),会访问到不满足条件的第一个值为止。

    

  注意:间隙锁唯一的目的是防止其他事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事物在同一间隙上采用间隙锁

MySQL高级9-锁的更多相关文章

  1. MySQL高级以及锁机制

    MySQL高级 推荐阅读: 锁:https://www.cnblogs.com/zwtblog/tag/锁/ 数据库:https://www.cnblogs.com/zwtblog/tag/数据库/ ...

  2. MySQL高级知识(十四)——行锁

    前言:前面学习了表锁的相关知识,本篇主要介绍行锁的相关知识.行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,但并发度高. 0.准备 #1.创建相关测试表tb_ ...

  3. MySQL高级知识(十三)——表锁

    前言:锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算机资源(如CPU.RAM.I/O等)的争用外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是 ...

  4. 「MySQL高级篇」MySQL锁机制 && 事务

    大家好,我是melo,一名大三后台练习生,最近赶在春招前整理整理发过的博客~! 引言 锁锁锁,到哪到离不开这桩琐事,并发琐事,redis琐事,如今是MySQL琐事,这其中琐事,还跟MySQL另一个重要 ...

  5. mysql笔记04 MySQL高级特性

    MySQL高级特性 1. 分区表:分区表是一种粗粒度的.简易的索引策略,适用于大数据量的过滤场景.最适合的场景是,在没有合适的索引时,对几个分区进行全表扫描,或者是只有一个分区和索引是热点,而且这个分 ...

  6. MySQL高级知识系列目录

    MySQL高级知识(一)——基础 MySQL高级知识(二)——Join查询 MySQL高级知识(三)——索引 MySQL高级知识(四)——Explain MySQL高级知识(五)——索引分析 MySQ ...

  7. Mysql 高级部分

    MySQL 高级部分   (1)索引(index)..................................................................... 1 (2) ...

  8. 干货:鲜为人用的MySQL高级特性与玩法!

    上一篇文章<万字总结:学习MySQL优化原理,这一篇就够了!>文末给大家留有两个开放的问题: 有非常多的程序员在分享时都会抛出这样一个观点:尽可能不要使用存储过程,存储过程非常不容易维护, ...

  9. Mysql高手系列 - 第26篇:聊聊如何使用mysql实现分布式锁

    Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 欢迎大家加我微信itsoku一起交流java.算法.数据库相关技术. 这是Mysql系列第26篇. 本篇我们使用my ...

  10. 【MySQL 高级】架构介绍

    MySQL高级 架构介绍 MySQL 简介 MySQL 安装 Docker 安装 参考链接 Linux 安装 参考链接 MySQL 配置文件 log-bin:二进制日志文件.用于主从复制.它记录了用户 ...

随机推荐

  1. ODOO13 之十 :Odoo 13开发之后台视图 – 设计用户界面

    Odoo 13开发之后台视图 – 设计用户界面 本文将学习如何为用户创建图形化界面来与图书应用交互.我们将了解不同视图类型和小组件(widgets)之间的差别,以及如何使用它们来提供更优的用户体验. ...

  2. JavaWeb编程面试题——导航

    引言 面试题==知识点,这里所记录的面试题并不针对于面试者,而是将这些面试题作为技能知识点来看待.不以刷题进大厂为目的,而是以学习为目的.这里的知识点会持续更新,目录也会随时进行调整. 关注公众号:编 ...

  3. Pytorch-如何在模型中引入可学习参数

    错误实例: def init(self): self.w1 = torch.nn.Parameter(torch.FloatTensor(1),requires_grad=True).cuda() s ...

  4. 免杀系列之去除Defender令牌权限

    本文展示了Windows存在的一个小bug,该问题允许攻击者绕过保护反恶意软件(AV/EDR)免受各种形式攻击的Windows安全机制(Windows Protected Process Light) ...

  5. 自然语言处理 Paddle NLP - 检索式文本问答-理论

    问答系统(Question Answering System,QA) 是信息检索系统的一种高级形式,它能用准确.简洁的自然语言回答用户用自然语言提出的问题.其研究兴起的主要原因是人们对快速.准确地获取 ...

  6. 暴力密码破解工具——Hydra

    Hydra简介 hydra中文意思为九头蛇,它是黑客组织thc开发一款开源暴力密码破解工具,可以在线破解多种密码,支持Windows Linux MAC系统安装使用(Kali Linux自带), 支持 ...

  7. go web学习(五)

    跟着刘旭老师学go web做的笔记 [Go Web 编程快速入门[Golang/Go语言](完结)] https://www.bilibili.com/video/BV1Xv411k7Xn/?p=27 ...

  8. elementui中deep的用法/deep/

    在做第一个vue项目时遇到了一个问题,在使用elementui中的Drawer(抽屉组件时),想要修改Drawer的标题,尝试着修改title的样式,但没有效果,尝试了很多方法,最后用/deep/解决 ...

  9. ChatGPT的探索与实践-业务应用篇

    本篇文章主要介绍在实际的开发过程当中,如何使用GPT帮助开发,优化流程,恰逢今年京东20周年庆,文末会介绍如何与618大促实际的业务相结合,来提升应用价值.全是干货,且本文所有代码和脚本都是利用GPT ...

  10. Mysql生成测试数据函数

    1.查看设置是否允许创建函数系统参数 show variables like 'log_bin_trust_function_creators'; 2.临时设置允许创建函数系统参数 set globa ...