我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL的全局锁和表级锁的具体使用

短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL的全局锁和表级锁的具体使用

目录
  • 前言
  • 全局锁
  • 表级锁
    • 表锁
    • 元数据锁(Metadata Locking,简称:MDL锁)
  • 总结
    • 参考资料

      前言

      在真实的企业开发环境中使用MySQL,MySQL肯定不会只有我一个人使用,而是一个团队显式的使用MySQL,或者是业务隐式的使用MySQL,那么多个用户或者客户端连接使用的时候,我们应该考虑一个问题:如果保证数据并发访问的一致性呢?这一篇我就来聊聊MySQL的锁,不涉及MySQL的事务隔离级别。

      全局锁

      MySQL的全局锁会关闭所有打开的表,并使全部的表处于只读状态,它们的命令为:

      
      # 全局锁,简称FTWRL
      FLUSH TABLES WITH READ LOCK;
      
      # 解锁命令
      UNLOCK TABLES;
      
      

      对FTWRL进行实验:(以下的所有实验都是在MySQL8.0.22完成的)

      session1 session2
      FLUSH TABLES WITH READ LOCK;
      select * from test limit 1;
      (正常返回结果)
      select * from test limit 1;
      (正常返回结果)
      insert into test(a,b,c) values(6,6,6);
      (报错)
      insert into test(a,b,c) values(8,8,8);# sql1
      (阻塞)
      UNLOCK TABLES;
      insert into test(a,b,c) values(8,8,8);# sql1
      (session1解锁后,sql1立马执行成功)

      从以上实验可以得出:当执行FTWRL后,所有的表变成了只读状态,其他更新的操作将会被阻塞。

      全局锁的主要作用就是做全库逻辑备份,也就是把数据库的每个表都select出来存成文本。

      当备份过程中,整个数据库处于只读状态,风险也是及其的大。如果是在主库备份,将会导致所有的业务表都不能修改数据;如果是在从库备份,这个时候从库不能执行主库传过来的binlog,会导致主从延迟。

      好在InnoDB存储引擎支持事务,mysqldump有一个参数single-transaction,可以在事务中创建一致性快照,然后进行所有表备份。在有这个参数下,备份期间可以进行数据修改,所以正常开发中建议使用InnoDB存储引擎。

      表级锁

      表级锁分为两种,一种是表锁,另一种是元数据锁。

      表锁

      表锁分为表读锁和表写锁,在MySQL的命令是:

      
      # 表读锁
      lock tables test read;
      
      # 表写锁
      lock tables test write;
      
      
      

      接下来通过实验看下表读锁和表写锁有什么区别吧

      表读锁

      session1 session2
      lock tables test read;
      select * from test limit1;
      (正常返回结果)
      select * from test limit 1;
      (正常返回结果)
      insert into test(a,b,c) values(6,6,6);
      (报错)
      insert into test(a,b,c) values(8,8,8); # sql1
      (阻塞)
      unlock tables;
      insert into test(a,b,c) values(8,8,8); # sql1
      (session1解锁后,sql1立马写入成功)

      在session1会话加上了表读锁,这个时候session1和session2都可以正常的读数据,但是session1写数据会报错,session2写数据会被阻塞,等到session1解锁了,session2的写数据才能执行成功。

      从这个实验可以得出:表加上了表读锁之后,本线程和其他线程都可以读数据,本线程写数据会报错,其他线程写数据会阻塞。

      表写锁

      session1 session2
      lock tables test write;
      select * from test limi1;
      (正常返回结果)
      select * from test limit 1; # sql1
      (阻塞)
      unlock tables;
      select * from test limit; # sql1
      (session1解锁后,sql1立马返回结果)
      lock tables test write;
      insert into test(a,b,c) values(6,6,6);
      (插入成功)
      insert into test(a,b,c) values(8,8,8);# sql 2
      (阻塞)
      unlock tables;
      insert into test(a,b,c) values(8,8,8);# sql2
      (session1解锁后,sql2立马执行成功)

      从以上实验可以得出:表加上了表写锁之后,本线程可以进行读写操作,其他线程的读写操作都会被阻塞。

      元数据锁(Metadata Locking,简称:MDL锁)

      在MySQL中,数据库的DDL不属于事务范畴,如果你在session1中select一行数据,这个时候session2给这张表新增了一列xxx,这个时候可能会出现事务特性被破坏、binlog顺序错乱等bug(MySQL官网上有公布出类似的bug,感兴趣可以自行去了解)。

      为了解决以上的问题,从MySQL5.5.3引入了元数据锁,MDL锁不需要显式使用,MySQL会默认加上,它的作用就是保证数据库读写正确性。以下全部用MDL表示元数据锁。

      当你对一张表进行增删查改的时候会默认加上MDL读锁;当你对一张表进行表结构更改的时候会默认加上MDL写锁。

      session1 session2 session3 session4
      begin;
      select * from test lmi1;
      (正常返回结果)
      select * from test limit 1;
      (正常返回结果)
      alter table test add d int;
      (阻塞)
      select * from test limit 1;
      (阻塞)

      一开始session1会话查询test的时候,获取到了MDL读锁,可以正常查询到数据。然后session2会话查询数据也会获取MDL读锁,不冲突,也可以正常查询到数据返回。

      但是到了session3会话的时候,需要获取MDL写锁,这个时候因为session1的MDL读锁没有释放,所以会阻塞。后面session4也需要MDL读锁,但是因为session3被阻塞了,所以session4也会被阻塞。

      假如这是一张线上业务表,这种场景将会使后面的任何操作都失效,表现出来就是这张表变得无法写和读。如果客户端配置了MySQL重试机制的话,会在超时的时候重新建立一个session会话重新请求,然后MySQL就会因为线程不停新增而崩溃。

      从上面的例子可以知道MDL锁是在语句执行的时候默认加上的,但是语句执行完是不会释放的,只有等整个事务提交了才会释放MDL锁。

      所以对于我们开发者来说,在工作中应该尽量避免慢查询、尽量保证事务及时提交、避免大事务等,对于DBA来说,也应该尽量避免在业务高峰期执行DDL操作。

      总结

      • 全局锁会让所有的表变成只读状态,所有更新操作都会被阻塞
      • 表读锁是本线程和其他线程都可以读,本线程写会报错,其他线程写会阻塞
      • 表写锁是本线程可以读写,其他线程读写都会阻塞
      • 引入MDL锁解决事务和DDL同时执行引发的bug

      参考资料

      • 《深入浅出MySQL》第二版:20.3.8 什么时候使用表锁
      • 《MySQL实战45讲》林晓斌

      到此这篇关于MySQL的全局锁和表级锁的具体使用的文章就介绍到这了,更多相关MySQL 全局锁和表级锁内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!

      免责声明:

      ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

      ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

      MySQL的全局锁和表级锁的具体使用

      下载Word文档到电脑,方便收藏和打印~

      下载Word文档

      猜你喜欢

      MySQL的全局锁和表级锁的具体使用

      目录前言全局锁表级锁表锁元数据锁(Metadata Locking,简称:MDL锁)总结参考资料前言在真实的企业开发环境中使用MySQL,MySQL肯定不会只有我一个人使用,而是一个团队显式的使用MySQL,或者是业务隐式的使用MySQL,
      2022-05-13

      MySQL的锁机制之全局锁和表锁的实现

      前言对mysql锁的总结学习,本文将围绕,加锁的概念,加锁的应用场景和优化,以php及不加锁会导致的问题这些方向进行总结学习。mysql的全局锁和表锁是本文的重编程点一、全局锁全局锁的介绍以及使用全局锁就是对整个数据库实例进行加锁。
      2023-01-15

      mysql 乐观锁和悲观锁的具体使用

      本文主要介绍了mysql 乐观锁和悲观锁的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
      2023-01-08

      mysql 乐观锁和悲观锁的具体使用

      目录悲观锁介绍(百科):1如果不采用锁,那么操作方法如下:2使用悲观锁来实现:补充:mysql select…for update的Row Lock与Table Lock乐观锁介绍:使用举例:以MySQL InnoDB为例悲观
      2023-01-09

      MySQL的表级锁,行级锁,排它锁和共享锁

      目录前言一、表级锁&行级锁二、排它锁&共享锁1. 测试不同事务之间排它锁和共享锁的兼容性2. 测试行锁加在索引项上三、串行化隔离级别测试前言如果我们和面试官聊到事务的问题,怎么回答呢?先说下事务是什么,因为我们业务是比较复杂的,不可能一
      2022-07-14

      mysql间隙锁的具体使用

      本文全面讲解MySQL间隙锁的使用方法,包括何时使用、类型、语法以及使用示例。间隙锁有助于防止幻读、保证范围查询完整性,但同时也存在资源消耗、死锁和影响查询性能等局限性。最佳实践建议在必要时使用、缩小锁范围、避免长时间持有锁,并使用死锁处理机制。
      mysql间隙锁的具体使用
      2024-04-02

      MySQL的表级锁,行级锁,排它锁和共享锁是什么

      这篇文章主要介绍“MySQL的表级锁,行级锁,排它锁和共享锁是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MySQL的表级锁,行级锁,排它锁和共享锁是什么”文章能帮助大家解决问题。前言先说下事
      2023-07-02

      MySQL表内连和外连的具体使用

      目录一. 内连接二. 外连接1. 左外连接2. 右外连接一. 内连接利用where子句对两种表形成的笛卡尔积进行筛选,其实就是内连接的一种方式另一种方式是inner joinselect 字段 from 表1 inner join 表2
      2023-10-18

      编程热搜

      目录