Mysql 的全局锁和表级锁

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实现这些访问规则的重要数据结构。根据加锁的范围,MySQL 里面的锁大致可以分成全局锁、表级锁和行锁三类。行级锁比较复杂,这篇文章就先分享全局锁和表级锁。还有就是需要说明的是,锁的设计比较复杂,文章中基本不会出现锁的具体实现细节,主要介绍的是碰到锁时的现象和其背后的原理。

Mysql 的全局锁和表级锁

数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实现这些访问规则的重要数据结构。根据加锁的范围,MySQL 里面的锁大致可以分成全局锁、表级锁和行锁三类。行级锁比较复杂,这篇文章就先分享全局锁和表级锁。还有就是需要说明的是,锁的设计比较复杂,文章中基本不会出现锁的具体实现细节,主要介绍的是碰到锁时的现象和其背后的原理。

当涉及到MySQL数据库的并发控制和多个客户端同时访问数据库时,全局锁是一种常见的锁机制。全局锁是一种在整个数据库实例上施加的锁,用于限制对整个数据库的访问,从而保护数据库在某些操作期间的一致性。然而,使用全局锁需要谨慎,因为它会对整个数据库的性能产生严重影响。

全局锁的使用场景

全局锁通常用于执行一些需要对整个数据库进行维护或更改的操作,以确保在此期间其他客户端不会对数据库进行修改。一些典型的使用场景包括:

  1. 备份操作: 在执行数据库备份期间,可以使用全局锁来确保备份的一致性,防止其他操作干扰备份过程。
  2. 恢复操作: 当需要进行数据库恢复操作时,可以使用全局锁来防止其他客户端对数据库进行写操作。
  3. 表维护: 在执行一些需要对整个表进行维护的操作,如ALTER TABLE语句,可以使用全局锁来确保操作的原子性。

使用全局锁的方法

使用全局锁通常需要执行以下步骤:

  1. 获取全局锁: 使用FLUSH TABLES WITH READ LOCK (FTWRL)语句来获取全局锁。这将会对所有表施加一个只读锁,阻止其他客户端的写操作。

    让整库都只读,听上去就很危险:如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;如果你在从库上备份,那么备份期间从库不能执行主库同步过来的 binlog,会导致主从延迟。看来加全局锁不太好。但是细想一下,备份为什么要加锁呢?

    有两张表。 一张 心愿单(t_wish_list) 表, 一张 购物车 (t_cart)表

    用户可以从心愿单中把物品添加到购物车中

    下面的例子就是在不加 FTWRL 的时候会出现的一种情况

    刚开始用户的心愿单中有两本书 book1 和 book2 购物车中有一件T恤

    然后开始备份心愿单表,过程中用户把book1 添加到了购物车中,最后再去备份购物车表,会出现数据不一致的问题

    image-20230804172043591

    也就是说,不加锁的话,备份系统备份的得到的库不是一个逻辑时间点,这个视图是逻辑不一致的

    但是你会说了,我平时 mysqldump的时候也没这么麻烦啊

    官方自带的逻辑备份工具是 mysqldump,当 mysqldump 使用参数 –single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。

    而由于 MVCC 的支持,这个过程中数据是可以正常更新的。

    那为什么还需要 FTWRL 呢?

    一致性读是好,但前提是引擎要支持这个隔离级别。比如,对于 MyISAM 这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用 FTWRL 命令了。

    所以,single-transaction 方法只适用于所有的表使用事务引擎的库。如果有的表使用了不支持事务的引擎,那么备份就只能通过 FTWRL 方法。这往往是 DBA 要求业务开发人员使用 InnoDB 替代 MyISAM 的原因之一。

  2. 执行维护操作: 在获取全局锁后,可以执行需要的维护操作,如备份、恢复或表维护。

  3. 释放全局锁: 在维护操作完成后,使用UNLOCK TABLES语句释放全局锁,允许其他客户端继续访问数据库。

注意事项和潜在风险

虽然全局锁在特定场景下很有用,但是它也有一些潜在的问题和风险:

  1. 性能影响: 获取全局锁会导致数据库实例的性能下降,因为其他客户端被限制在只读操作。
  2. 长时间锁定: 如果获取全局锁后的维护操作耗时很长,会导致其他客户端长时间地无法进行写操作,影响应用的正常运行。
  3. 锁冲突: 如果有多个操作需要获取全局锁,可能会出现锁冲突,导致某些操作无法执行。
  4. 数据一致性: 虽然全局锁可以确保维护操作的一致性,但是在释放锁之前,其他操作可能会被阻塞,导致数据访问的延迟。

全局锁是MySQL中的一种重要锁机制,用于在执行维护操作时保护数据库的一致性。然而,由于全局锁会对数据库的性能产生影响,并可能导致一些潜在问题,因此在使用全局锁时需要谨慎考虑,确保在适当的情况下使用,同时尽量减少锁的持有时间,以便降低影响。

表级锁

MySQL 里面表级别的锁有两种:

表锁

表锁的语法是 lock tables … read/write。与 FTWRL 类似,可以用unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。

需要注意,lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

就像如果在某个线程 A 中执行 lock tables t1 read, t2 write; 这个语句,则其他线程写 t1、读写 t2 的语句都会被阻塞。同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。连写 t1 都不允许,自然也不能访问其他表。

而对于 InnoDB 这种支持行锁的引擎,一般不使用 lock tables 命令来控制并发,毕竟锁住整个表的影响面还是太大。

元数据锁(meta data lock,MDL)

MDL 是 MySQL 数据库内部的锁机制,用于管理和保护数据库对象的元数据。元数据锁定是用来控制对数据库对象的并发操作,以确保数据库的一致性和完整性。MDL 的主要作用是控制并发操作,防止多个客户端对同一数据库对象进行不一致的操作。例如,当一个客户端正在修改表结构时,另一个客户端不能同时修改相同的表结构,以防止数据不一致或损坏。

MySQL 中的 MDL 有多种类型,分别用于不同的元数据对象,如表、锁、函数等。每种类型的 MDL 都有不同的作用和范围,用于控制不同级别的并发操作。客户端在需要访问元数据对象时,会请求获取相应的 MDL。如果其他客户端已经持有了相同类型的 MDL,请求的客户端可能会被阻塞,直到现有的 MDL 被释放。一旦操作完成,客户端会释放其持有的 MDL。

当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

  • 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。

  • 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

但是在实际过程中需要注意以下的问题:

  • 锁等待:如果多个客户端争夺相同的 MDL,会导致一些客户端等待。因此,在设计数据库架构时,应考虑如何减少锁争用,以避免性能问题。
  • 长事务:长事务可能会持有 MDL 很长时间,从而阻塞其他事务的操作。因此,应该尽量避免长事务,或者在必要时释放 MDL。
  • 死锁:不当的 MDL 使用可能导致死锁,因此在应用程序中应该避免在一个事务中同时获取多个 MDL。
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
10天前
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL里常见的几种锁
34 3
|
1天前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
4 1
|
16天前
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
45 2
|
16天前
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
9 1
|
1天前
|
存储 关系型数据库 MySQL
MySQL锁,锁的到底是什么?
【10月更文挑战第16天】MySQL 锁锁定的是与数据和资源相关的对象,其目的是为了保证数据的一致性、避免冲突,并在并发环境下合理协调事务或操作的执行。理解锁的对象和意义对于优化数据库性能、处理并发问题至关重要。
12 0
|
3天前
|
关系型数据库 MySQL 数据库
mysql锁详解
通过理解并合理运用MySQL中的锁机制,开发者可以有效管理数据库并发访问,平衡性能与数据一致性需求。更多关于MySQL锁的深入探讨和最佳实践,请参考专业的数据库管理资源[[深入MySQL锁机制详解
7 0
|
26天前
|
存储 SQL 关系型数据库
MySQL 的锁机制,那么多的锁,该怎么区分?
MySQL 的锁机制,那么多的锁,该怎么区分?
28 0
|
9天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
43 6
|
7天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
38 3
Mysql(4)—数据库索引
|
9天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
27 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用