MySQL 元数据锁查询

为什么引入MDL锁

对于引入MDL,其主要解决了2个问题,一个是事务隔离问题,比如在可重复隔离级别下,会话A在2次查询期间,会话B对表结构做了修改,两次查询结果就会不一致,无法满足可重复读的要求;另外一个是数据复制的问题,比如会话A执行了多条更新语句期间,另外一个会话B做了表结构变更并且先提交,就会导致slave在重做时,先重做alter,再重做update时就会出现复制错误的现象。

什么是MDL

在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

元数据锁是server层的锁,表级锁,每执行一条DML、DDL语句时都会申请MDL锁,DML操作需要MDL读锁,DDL操作需要MDL写锁(MDL加锁过程是系统自动控制,无法直接干预,读读共享,读写互斥,写写互斥),申请MDL锁的操作会形成一个队列,队列中写锁获取优先级高于读锁。一旦出现写锁等待,不但当前操作会被阻塞,同时还会阻塞后续该表的所有操作。

事务一旦申请到MDL锁后,直到事务执行完才会将锁释放。(这里有种特殊情况如果事务中
包含DDL操作,mysql会在DDL操作语句执行前,隐式提交commit,以保证该DDL语句操作
作为一个单独的事务存在,同时也保证元数据排他锁的释放)。

查看元数据锁

在MySQL5.7中,performance_schema库中新增了metadata_locks表,专门记录MDL的相关信息。首先要开启metadata_locks锁记录,执行如下SQL开启:(8.0默认打开)

UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'
WHERE NAME ='global_instrumentation';
 
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES'
WHERE NAME ='wait/lock/metadata/sql/mdl';

#配置文件中添加,重启生效
performance-schema-instrument = wait/lock/metadata/sql/mdl=ON

以8.0为例模拟MDL锁和锁冲突

mysql> select * from performance_schema.metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA      | OBJECT_NAME    | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE   | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | performance_schema | metadata_locks | NULL        |       139653546092288 | SHARED_READ | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             402 |              4 |
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
1 row in set (0.00 sec)

开启一个session

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from actor;


mysql> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
|             362 |
+-----------------+
1 row in set (0.00 sec)

再次查询

mysql> select * from performance_schema.metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA      | OBJECT_NAME    | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE   | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | sakila             | actor          | NULL        |       139653546092096 | SHARED_READ | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             402 |             39 |
| TABLE       | performance_schema | metadata_locks | NULL        |       139653682246880 | SHARED_READ | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             403 |              5 |
+-------------+--------------------+-------------

此时再次查看metadata_lock表,发现多了一条actor表的加锁记录,加锁类型为SHARED_READ,且状态是已授予(GRANTED)。

如果在session2执行select期间且事务未提交,另外一个session执行了一个DDL操作,此时就会产生互斥的metadata lock:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> drop table actor;

mysql> select * from performance_schema.metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA      | OBJECT_NAME    | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE           | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | sakila             | actor          | NULL        |       139653546092096 | SHARED_READ         | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             402 |             39 |
| GLOBAL      | NULL               | NULL           | NULL        |       139653617167616 | INTENTION_EXCLUSIVE | STATEMENT     | GRANTED     | sql_base.cc:5436  |             404 |             36 |
| BACKUP LOCK | NULL               | NULL           | NULL        |       139653616499728 | INTENTION_EXCLUSIVE | TRANSACTION   | GRANTED     | sql_base.cc:5443  |             404 |             36 |
| SCHEMA      | sakila             | NULL           | NULL        |       139653615812928 | INTENTION_EXCLUSIVE | TRANSACTION   | GRANTED     | sql_base.cc:5423  |             404 |             36 |
| TABLE       | sakila             | actor          | NULL        |       139653624258944 | EXCLUSIVE           | TRANSACTION   | PENDING     | sql_parse.cc:5768 |             404 |             36 |
| TABLE       | performance_schema | metadata_locks | NULL        |       139653682246880 | SHARED_READ         | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             403 |              6 |
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
6 rows in set (0.00 sec)

查看metadata_locks表记录 发现actor表有MDL锁冲突( SHARED_READ 和EXCLUSIVE 互斥)

通过查看 show processlist;也看到pid为364的回话,在等到元数据锁释放Waiting for table metadata lock

mysql> show processlist;
+-----+-----------------+-----------+--------+---------+--------+---------------------------------+------------------+
| Id  | User            | Host      | db     | Command | Time   | State                           | Info             |
+-----+-----------------+-----------+--------+---------+--------+---------------------------------+------------------+
|   5 | event_scheduler | localhost | NULL   | Daemon  | 412694 | Waiting on empty queue          | NULL             |
| 362 | root            | localhost | sakila | Sleep   |    441 |                                 | NULL             |
| 363 | root            | localhost | NULL   | Query   |      0 | init                            | show processlist |
| 364 | root            | localhost | sakila | Query   |    124 | Waiting for table metadata lock | drop table actor |
+-----+-----------------+-----------+--------+---------+--------+---------------------------------+------------------+

元数据锁为什么会造成系统崩溃

举一个简单例子,session1启动一个事务,对表actor执行一个简单的查询;session2对actor加一个字段;session3来对actor做一个查询;session4来对actor做一个update,各个session串行操作。

前面提到过申请MDL锁的操作会形成一个队列,队列中写锁获取优先级高于读锁。一旦出现写锁等待,不但当前操作会被阻塞,同时还会阻塞后续该表的所有操作。

也就是由于session1的一个事务没有提交,导致session2的DDL操作被阻塞,session3和session4本身不会被session1阻塞,但由于在锁队列中,session2排队更早,它准备加的是metadata lock写锁,阻塞了session3和session4的读锁。如果students是一个执行频繁的表,show processlist会发现大量‘waiting for table metadata lock’的线程,数据库连接很快就会消耗完,导致业务系统无法正常响应。

如何监控元数据锁

metadata_locks是5.7中被引入,记录了metadata lock的相关信息,包括持有对象、类型、状态等信息。
单纯查询metadata_locks这个表无法得出具体的阻塞关系,也无法得知什么语句造成的阻塞,这里要关联另外两个表performance_schema.thread和performance_schema.events_statements_history,thread表可以将线程id和show processlist中id关联,events_statements_history表可以得到事务的历史sql,关联得到一条监控元数据锁的sql语句。

mysql> SELECT locked_schema,
    -> locked_table,
    -> locked_type,
    -> waiting_processlist_id,
    -> waiting_age,
    -> waiting_query,
    -> waiting_state,
    -> blocking_processlist_id,
    -> blocking_age,
    -> substring_index(sql_text,"transaction_begin;" ,-1) AS blocking_query,
    -> sql_kill_blocking_connection
    -> FROM 
    -> ( 
    -> SELECT 
    -> b.OWNER_THREAD_ID AS granted_thread_id,
    -> a.OBJECT_SCHEMA AS locked_schema,
    -> a.OBJECT_NAME AS locked_table,
    -> "Metadata Lock" AS locked_type,
    -> c.PROCESSLIST_ID AS waiting_processlist_id,
    -> c.PROCESSLIST_TIME AS waiting_age,
    -> c.PROCESSLIST_INFO AS waiting_query,
    -> c.PROCESSLIST_STATE AS waiting_state,
    -> d.PROCESSLIST_ID AS blocking_processlist_id,
    -> d.PROCESSLIST_TIME AS blocking_age,
    -> d.PROCESSLIST_INFO AS blocking_query,
    -> concat('KILL ', d.PROCESSLIST_ID) AS sql_kill_blocking_connection
    -> FROM performance_schema.metadata_locks a JOIN performance_schema.metadata_locks b ON a.OBJECT_SCHEMA = b.OBJECT_SCHEMA AND a.OBJECT_NAME = b.OBJECT_NAME
    -> AND a.lock_status = 'PENDING'
    -> AND b.lock_status = 'GRANTED'
    -> AND a.OWNER_THREAD_ID <> b.OWNER_THREAD_ID
    -> AND a.lock_type = 'EXCLUSIVE'
    -> JOIN performance_schema.threads c ON a.OWNER_THREAD_ID = c.THREAD_ID JOIN performance_schema.threads d ON b.OWNER_THREAD_ID = d.THREAD_ID
    -> ) t1,
    -> (
    -> SELECT thread_id, group_concat( CASE WHEN EVENT_NAME = 'statement/sql/begin' THEN "transaction_begin" ELSE sql_text END ORDER BY event_id SEPARATOR ";" ) AS sql_text
    -> FROM
    -> performance_schema.events_statements_history
    -> GROUP BY thread_id
    -> ) t2
    -> WHERE t1.granted_thread_id = t2.thread_id \G
*************************** 1. row ***************************
               locked_schema: sakila
                locked_table: actor
                 locked_type: Metadata Lock
      waiting_processlist_id: 364
                 waiting_age: 248
               waiting_query: drop table actor
               waiting_state: Waiting for table metadata lock
     blocking_processlist_id: 362
                blocking_age: 565
              blocking_query: select * from actor
sql_kill_blocking_connection: KILL 362
1 row in set (0.00 sec)

根据显示结果,processlist_id为362的线程阻塞了364的线程,我们需要kill 362即可解锁。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android OpenGLES开发:EGL环境搭建

努力&#xff0c;不是为了要感动谁&#xff0c;也不是要做给哪个人看&#xff0c;而是要让自己随时有能力跳出自己厌恶的圈子&#xff0c;并拥有选择的权利&#xff0c;用自己喜欢的方式过一生&#xff01; EGL是什么&#xff1f; 谈到openGL开发我们就不得不说EGL&#xff0c…

零基础5分钟上手亚马逊云科技-开发云原生网站应用

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…

调度台在现代社会中发挥哪些重要作用

在当今这个高度信息化、快节奏的社会中&#xff0c;调度台作为各行各业运行管理的中枢神经&#xff0c;正发挥着日益重要的作用。它不仅是一个物理上的工作平台&#xff0c;更是信息汇聚、指令发出、资源调配的核心节点&#xff0c;对于保障社会正常运转、提升服务效率、应对突…

tkcalendar中的DateEntry

tkcalendar中的DateEntry可进行时间选择&#xff0c;在Python环境中可以直接使用&#xff0c;但是打包过程中&#xff0c;pyinstaller -F -w -i nss.ico xxx.py,DateEntry是用不了&#xff0c;不显示&#xff0c;打包使用pyinstaller -F -w -i nss.ico --hidden-import babel.n…

spring boot(学习笔记第十九课)

spring boot(学习笔记第十九课) Spring boot的batch框架&#xff0c;以及Swagger3(OpenAPI)整合 学习内容&#xff1a; Spring boot的batch框架Spring boot的Swagger3&#xff08;OpenAPI&#xff09;整合 1. Spring boot batch框架 Spring Batch是什么 Spring Batch 是一个…

dp练习【4】

最长数对链 646. 最长数对链 给你一个由 n 个数对组成的数对数组 pairs &#xff0c;其中 pairs[i] [lefti, righti] 且 lefti < righti 。 现在&#xff0c;我们定义一种 跟随 关系&#xff0c;当且仅当 b < c 时&#xff0c;数对 p2 [c, d] 才可以跟在 p1 [a, b…

Ubuntu环境的MySql下载安装

下载压缩包 此文章下载的mysql版本位5.7.29 sudo wget https://downloads.mysql.com/archives/get/p/23/file/mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar解压缩 sudo tar -xvf mysql-server_5.7.29-1ubuntu18.04_amd64.deb-bundle.tar命令解释 -x&#xff1a;…

鸿蒙MPChart图表自定义(四)短刻度线

对于图表中的x轴效果&#xff0c;我们有时想要实现如图所示的特定刻度线。若需绘制x轴的短刻度线&#xff0c;我们可以利用现有资源&#xff0c;将原本的网格线稍作修改&#xff0c;只需绘制一条简洁的短线即可达到目的。 具体的方法就是写一个类MyXAxisRender继承自XAxisRend…

【补-网络安全】日常运维(二)终端端口占用排查

文章目录 一、利用ipconfig、netstat 命令行统计二 、策略封禁IP 引言:检查频繁,第一步我们梳理完资产,第二步应该对资产终端进行一个排查,诊断把脉,了解清楚系统的端口占用及开放情况 一、利用ipconfig、netstat 命令行统计 1.先用ipconfig定位该终端的IP地址 2.明确IP地址后…

汇编语言在虚拟机中输出“Hello World!”

1.软件 Nasmide64.exe(李忠老师编写) Fixvhdw64.exe(李忠老师编写) VirtualBox虚拟机(免费 开源) 2.过程 01.Fixvhdw64.exe输入以下代码: mov ax,0xb800 mov ds,ax mov byte [0x00],H mov byte [0x02],e mov byte [0x04],l mov byte [0x06],l mov byte [0x08],o mov byte…

x-cmd pkg | tig - 基于 nucurses 的 git 文本模式界面

目录 简介首次用户快速实验指南功能特点类似工具与竞品进一步探索 简介 tig 由 Jonas Fonseca 于 2006 年使用 C 语言创建的 git 交互式文本命令行工具。旨在开启交互模式快速浏览 git 存储库的信息以及 git 命令的运行。 首次用户快速实验指南 本文的 demo 展现了如何通过 …

2024年高教杯国赛(D题)数学建模竞赛解题思路|完整代码论文集合

我是Tina表姐&#xff0c;毕业于中国人民大学&#xff0c;对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在&#xff0c;我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…

2024国赛数学建模ABC题思路模型

完整的思路模型请查看文末名片 完整的思路模型请查看文末名片 完整的思路模型请查看文末名片

精通Transformer,从零开始构建最先进的NLP模型(附PDF)

国内第1本Transformer——变形金刚红书 如果一定要说未来谁能引领人工智能世界&#xff0c;是Transformer而非chatGPT&#xff01; 编辑推荐★★★★★ ChatGPT红得发紫&#xff0c;强得让人类心悸。 但在它的背后&#xff0c;还隐藏着一位真正的大佬。 它的名字叫做——T…

科研绘图系列:R语言PCoA图(PCoA plot)

文章目录 介绍PCoA图的作用:说明的问题:加载R包导入数据数据预处理画图参考介绍 PCoA(主坐标分析,Principal Coordinate Analysis)是一种多维数据的降维技术,它用于探索高维空间中样本之间的关系。PCoA通常用于生态学、遗传学和其他领域的数据分析,以揭示样本或个体之间…

基于.NET6的WPF基础总结(上)

目录 一.常用属性介绍 二、 程序退出方式 三、布局样式 3.1 Panel的附加属性ZIndex 3.2 Grid(网格)布局 3.3 UniformGrid&#xff08;均分布局&#xff09; 3.4 StackPanel&#xff08;堆积面板&#xff09; 3.5 WrapPanel&#xff08;换行面板&#xff09; 3.6 Doc…

在模板中使用 Django 会话

在 Django 中使用会话&#xff08;session&#xff09;可以让你在用户访问网站的过程中存储和访问临时数据。我们可以利用会话在速度计算器的例子中存储和显示上次计算的结果。 1、问题背景 在 Django 中&#xff0c;可以使用会话来存储用户数据。在某些情况下&#xff0c;我们…

俄罗斯版微信遭遇大规模数据泄露,安全问题再引关注

据报道&#xff0c;俄罗斯最大的社交媒体和网络服务VK&#xff08;VKontakte&#xff09;遭遇了大规模的数据泄露事件&#xff0c;该事件对大量用户造成了影响。据非法市场BreachForums上一位名为Hikki-Chan的威胁行为者声称&#xff0c;2024年9月&#xff0c;VK的数据在论坛上…

Stream 流式编程

优质博文&#xff1a;IT-BLOG-CN 大家都知道可以将Collection类转化成流Stream进行操作&#xff08;Map并不能创建流&#xff09;&#xff0c;代码变得简约流畅。我们先看下流的几个特点&#xff1a; 1、流并不存储元素。这些元素可能存储在底层的集合中&#xff0c;或者是按需…

VMwareWorkstation安装Kali系统教程

Kali系统&#xff0c;全名为Kali Linux&#xff0c;为渗透测试和网络安全领域提供一个全面的工具集合。Kali系统预装了各种用于渗透测试和漏洞利用的工具&#xff0c;包括端口扫描、密码破解、网络嗅探、漏洞分析等。这些工具可以帮助安全专业人员评估和测试网络的安全性&#…