什么情况下 MySQL 连查询都能被阻塞?

news2025/1/16 18:40:08

MySQL 的锁也是不少,在哪种情况下会连查询都能被阻塞?这是一个有意思的问题。

工作中,很多开发和 DBA 可能接触较多的锁也就行锁了。对于行锁,阻塞写能理解,阻塞读实在是想不到。能阻塞读的那肯定是颗粒度更大的锁了,比如表级别的。

作者:贾特特,MySQL DBA 从业者,公众号『数据库运维札记』作者,目前任职于某游戏公司担任DBA工程师

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 2000 字,预计阅读需要 8 分钟。

MySQL 的锁也是不少,在哪种情况下会连查询都能被阻塞?这是一个有意思的问题。

工作中,很多开发和 DBA 可能接触较多的锁也就行锁了。对于行锁,阻塞写能理解,阻塞读实在是想不到。能阻塞读的那肯定是颗粒度更大的锁了,比如表级别的。

本文操作环境为 MySQL 8.0。

MySQL 表级锁有两种实现

  1. 服务器(SERVER)层:本层的锁定主要是元数据锁(metadata lock,MDL)。
  2. 存储引擎(ENGINE)层:本层不同的存储引擎可能会实现不同的锁定策略。例如 MyISAM 引擎实现了表级锁,InnoDB 存储引擎实现了行级锁和表级锁,其中表级锁是通过意向锁体现的。

元数据锁(MDL)是由 SERVER 层管理,用于锁定数据库对象的元数据信息,如:表结构、索引等。元数据锁可以阻止对表结构的改变,以确保数据定义的一致性。

元数据锁的类型

点击放大

每种锁类型后面会详细介绍。简单来说,对于元数据锁而言,当对一个表进行增删改查操作的时候,会加 元数据读锁。当对表数据结构进行变更的时候会加 元数据写锁它读写互斥,写写互斥,只有读读不冲突。

意向锁是在存储引擎层实现的,用于协调不同事务对表级锁和行级锁的请求。当一个事务在某个层次(表级或行级)上获取锁时,会首先获取对应层次的意向锁,以提示其他事务该事务在该层次上有锁的意向。这样可以在更高层次上减少锁冲突,提高并发性能。

InnoDB 存储引擎的意向锁种类

  1. 意向共享锁(Intention Shared Lock,IS):事务打算给数据行加共享锁(S 锁)。
  2. 意向排他锁(Intention Exclusive Lock,IX):事务打算给数据行加排他锁(X 锁)。

这样看来,表对象不可读写有种情况可能就是元数据锁互斥所导致的。

Waiting for table metadata lock

本节中未完成的读写事务,在实际中可能是未完成的大事务,也可能是未显式结束的事务。

元数据锁互斥(未完成的读事务)

会话 1 执行:有未完成的读事务,此时获取了元数据共享读锁。

MDL_SHARED_READ: 这个锁允许会话读取表的数据,并允许其他会话获取 SHARED_READ 或 SHARED_WRITE 锁,但不允许获取 SHARED_NO_READ_WRITE 或 EXCLUSIVE 锁。

会话 2 执行:ALTER 表结构变更语句,此时 ALTER 语句要获取元数据排它锁。

MDL_EXCLUSIVE: 这个锁允许会话读取和修改表的数据和结构,但不允许其他会话获取任何类型的锁。

元数据锁互斥等待,之后其他会话对于所涉及表不可读写。

元数据锁互斥(未完成的写事务)

会话 1 执行:有未完成的写事务,此时获取了元数据写锁。

MDL_SHARED_WRITE: 这个锁允许会话读取和修改表的数据,并允许其他会话获取 SHARED_READ 锁,但不允许获取 SHARED_WRITE、SHARED_NO_READ_WRITE 或 EXCLUSIVE 锁。

会话 2 执行:ALTER 表结构变更语句,此时 ALTER 语句要获取元数据排它锁。

MDL_EXCLUSIVE:这个锁允许会话读取和修改表的数据和结构,但不允许其他会话获取任何类型的锁。

元数据锁互斥等待,之后其他会话对于所涉及表不可读写。

LOCK TABLES ... READ/WRITE

LOCK TABLES 可以显式获取表锁,需要注意的是会话只能自己获取和释放表锁。UNLOCK TABLES 可以显式释放当前会话的表锁。

LOCK TABLES … READ

会话 1 执行:lock tables db_version read;

MDL_SHARED_READ_ONLY: 这个锁允许会话读取表的数据,并允许其他会话获取 SHARED_READ 锁,但不允许获取 SHARED_WRITE、SHARED_NO_READ_WRITE 或 EXCLUSIVE 锁。

此时 db_version 加了元数据共享只读锁。

会话 2 执行:ALTER 表结构变更语句,此时 ALTER 语句要获取元数据排它锁,元数据锁互斥等待。

之后所涉及表对象将不可读写。

LOCK TABLES … WRITE

会话 1 执行:lock tables db_version write;

MDL_SHARED_NO_READ_WRITE: 这个锁允许当前会话读取和修改表的数据,但不允许其他会话获取任何类型的锁。

此时 db_version 加上了独占写锁。只能在 会话 1 读写,它会阻止其他会话获取任何类型的锁。

因此其他会话既不能读也不能写,当然查询也会被阻塞了。

需要注意的是,此时 会话 1 对其他表也会不可读写。

FLUSH TABLES & WAITING FOR TABLE FLUSH

FLUSH TABLES 关闭所有打开的表,强制关闭所有正在使用的表,并刷新准备好的语句缓存。当存在活动的 LOCK TABLES 时,不允许执行 FLUSH TABLES 操作。

FLUSH TABLES

  1. ALTER 表结构时,执行 FLUSH TABLES 阻塞,从而导致表对象不可读写。

  1. LOCK TABLES 后,执行 FLUSH TABLES 会被阻塞,从而导致表对象不可读写。

    • 会话 1 执行:lock tables db_version read;
    • 会话 2 执行:flush tables;

此时,会话 2 会被阻塞,其他会话对所涉及表将不可读写。SHOW PROCESSLIST 中会提示 Waiting for table flush

需要说明的是,会话 1 执行完 lock tables...read lock 后,其他会话执行 DML 增删改语句,虽然会因获取不到元数据锁而阻塞,但不会阻塞其他会话执行 SELECT 查询。

换言之,执行 lock tables...read 后,当遇到元数据锁排它锁互斥阻塞(ALTER 语句)或者 FLUSH TABLES 发生阻塞后,才会发生所涉及表对象不可读写。

处理延伸

如何处理并找到源头 SQL 呢?

对于因元数据锁互斥而导致的表不可读写,一般可以通过 sys 库下的内置视图来查看。可能会涉及的表:

sys.schema_table_lock_waits: 可直接通过 sys 下内置视图,看到元数据锁互斥的相关信息。

information_schema.innodb_trx: 找到长时间未提交的事务。

对于因 FLUSH TABLE 等待而导致的表不可读写的场景,通过上述视 图/表 是不一定有数据的。大致会有以下两种情况:

Waiting for table flush: 可以按如下方式寻找源头。这种情况主要出现于因 FLUSH TABLES 而等待后,执行 DML 语句。

SELECT
  b.PROCESSLIST_ID,
  b.THREAD_ID,
  a.OBJECT_NAME,
  a.LOCK_TYPE,
  a.LOCK_STATUS,
  b.PROCESSLIST_STATE 
FROM
  `performance_schema`.metadata_locks a
  LEFT JOIN `performance_schema`.threads b ON a.OWNER_THREAD_ID = b.THREAD_ID 
WHERE
  a.OBJECT_SCHEMA = 'tmp';

也可以通过线程 ID 找到会话最近的 10 条语句进一步判断确认。

select THREAD_ID,event_id,sql_text from 
`performance_schema`.events_statements_history
where THREAD_ID =  14503
order by event_id;

Waiting for table metadata lock: 可以参考元数据锁互斥而导致的表不可读写处理。这种情况主要出现于因 FLUSH TABLES 而等待后,执行 DDL 语句如 ALTER TABLE

总结

以下情况会导致表对象不可读写:

  1. Waiting for table metadata lock 而导致的表对象不可读写。
  2. Waiting for table flush 而导致的表对象不可读写。

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。

SQLE 获取

类型地址
版本库https://github.com/actiontech/sqle
文档https://actiontech.github.io/sqle-docs/
发布信息https://github.com/actiontech/sqle/releases
数据审核插件开发文档https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑怎么压缩图片?压缩图片并不难

电脑怎么压缩图片?随着数字时代的来临,我们每天都在与大量的图片打交道,无论是社交媒体上的个人照片,还是工作中的设计图片,或是网页上的广告图片。然而,高质量的图片往往意味着大文件大小,这不…

如何将jsp项目转成springboot项目

昨天说过,springboot推荐使用Thymeleaf作为前后端渲染的模板引擎,为什么推荐用Thymeleaf呢,有以下几个原因: 动静结合:Thymeleaf支持HTML原型,允许在HTML标签中增加额外的属性来实现模板与数据的结合。这样…

Linux的基础IO:文件系统

目录 学前补充 磁盘的存储结构 OS如何对磁盘的存储进行逻辑抽象 细节内容 文件的增删改查 学前补充 问题:计算机只认二进制,即0、1,什么是0、1? 解释:0、1在物理层面可能有不同的表现,0、1是数字逻辑…

美股订单类型有哪些

美股交易中,订单类型是投资者执行交易指令的重要工具。了解不同类型的订单,可以帮助投资者制定更有效的交易策略,并控制风险。 1. 市价单:快速成交,不惧踏空 市价单(Market Order)是一种以当时…

【NodeMCU实时天气时钟温湿度项目 5】获取关于城市天气实况和天气预报的JSON信息(心知天气版)

| 今天是第五专题内容,主要是介绍如何从心知天气官网,获取包含当前天气实况和未来 3 天天气预报的JSON数据信息。 在学习获取及显示天气信息前,我们务必要对JSON数据格式有个深入的了解。 如您需要了解其它专题的内容&#xf…

鸿蒙内核源码分析(ELF格式篇) | 应用程序入口并不是main

阅读之前的说明 先说明,本篇很长,也很枯燥,若不是绝对的技术偏执狂是看不下去的.将通过一段简单代码去跟踪编译成ELF格式后的内容.看看ELF究竟长了怎样的一副花花肠子,用readelf命令去窥视ELF的全貌,最后用objdump命令…

吴恩达2022机器学习专项课程C2(高级学习算法)W1(神经网络):2.5 更复杂的神经网络

目录 示例填写第三层的层数1.问题2.答案 公式:计算任意层的激活值激活函数 示例 层数有4层,不包括输入层。 填写第三层的层数 1.问题 你能把第二个神经元的上标和下标填写出来吗? 2.答案 根据公式g(wxb),这里的x对应的是上…

Liunx系统怎么设置免密登录?看这一篇!

远程口令爆破也是黑客常用的手段,有些人安全意识薄弱的会设置一些简单的密码,这样分分钟会被黑客爆破进去,一旦操作系统沦陷,里面的数据必将被黑客一览无余,使用免密登录可以有效降低密码被爆破的风险,具体…

C++学习第十二天(继承)

1、继承的概念以及定义 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行拓展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构&#x…

光伏设计的核心要素有哪些?

光伏设计是可再生能源领域中的一个重要分支,它涉及到将太阳能转换为电能的整个过程。在光伏系统的设计和构建过程中,有几个核心要素需要被充分考虑和精确计算,以确保系统的性能、可靠性和经济效益。 一、光照条件分析 光照条件是光伏系统设计…

从Python整数变量内存大小占用28字节谈起

实验结果 本机环境64位Python 3.12 内存布局图 0 4 8 12 16 20 24 28 |----------|----------|----------|----------|----------|----------|----------| | ob_refcnt | ob_type | ob_digit | …

C++初识多态(1)

1.多态要解决的问题(引入) 任何一种机制的存在,必然是有其存在的意义的,例如我们前面学过的函数重载,运算符重载,以及引用等等,都是解决一些特殊问题的; 下面通过一些具体的例子&a…

Postman的一些使用技巧

Postman 是一个流行的 API 开发工具,用于设计、开发、测试、发布和监控 API。在现代web开发中使用非常广泛。后端开发必备而且必会的工具。 目录 1.配置环境变量 2.动态变量 3.脚本 4.测试 5.模拟 6.监控 7.集合运行器 8.响应保存 9.请求历史 10.同步请求…

6、随机森林(Random forests)

Random forests started a revolution in machine learning 20 years ago. For the first time, there was a fast and reliable algorithm which made almost no assumptions about the form of the data, and required almost no preprocessing. In today’s lesson, you’ll…

数据结构——实现通讯录(附源码)

乐观学习,乐观生活,才能不断前进啊!!! 我的主页:optimistic_chen 我的专栏:c语言 点击主页:optimistic_chen和专栏:c语言, 创作不易,大佬们点赞鼓…

党建教育vr虚拟现实展厅真正实现了绿色、低碳的展示方式

在数字化浪潮席卷的今天,传统企业门户官网已难以满足企业日益增长的展示需求。面对这一挑战,北京华锐凭借深厚的行业经验和领先的技术实力,为您提供全新的元宇宙虚拟展厅制作服务,助您轻松打破现实与虚拟的界限,开启企…

Flutter笔记:Widgets Easier组件库(11)- 使用提示吐丝(Tip Toasts)

Flutter笔记 Widgets Easier组件库(11)使用提示吐丝 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this …

【文献解析】NeRF的原理是什么

论文:https://arxiv.org/abs/2003.08934 TensorFlow代码:https://github.com/bmild/nerfPyToch代码:https://github.com/yenchenlin/nerf-pytorch 一、文章概述 1.问题导向 从新视点生成照片级真实感输出需要正确处理复杂的几何体和材质反…

WEB基础--JDBC操作数据库

使用JDBC操作数据库 使用JDBC查询数据 五部曲:建立驱动,建立连接,获取SQL语句,执行SQL语句,释放资源 建立驱动 //1.加载驱动Class.forName("com.mysql.cj.jdbc.Driver"); 建立连接 //2.连接数据库 Stri…

提高谷歌抓取成功率:代理IP的7个使用误区

在当今数字化时代,数据采集和网络爬取已成为许多企业和个人必不可少的业务活动。对于爬取搜索引擎数据,特别是Google,使用代理IP是常见的手段。然而,使用代理抓取Google并不是一件轻松的事情,有许多常见的误区可能会导…