独家揭秘丨GreatSQL 的MDL锁策略升级对执行的影响

news2024/9/20 23:05:55

独家揭秘丨GreatSQL 的MDL锁策略升级对执行的影响

一、MDL锁策略介绍

GreatSQL 的MDL锁有个策略方法类MDL_lock_strategy,它根据对象的类型分为了scope类型和object类型,前者主要用于GLOBAL, COMMIT, TABLESPACE, BACKUP_LOCK and SCHEMA ,RESOURCE_GROUPS,FOREIGN_KEY,CHECK_CONSTRAINT,BACKUP_TABLES类型,后者主要用于DD表的锁表,本次主要介绍后者的策略原理和策略改变的动机以及对执行的影响。

MDL以表为单位进行锁表,包括3个主要的存储方式:m_fast_path_state位图、m_granted队列、m_waiting队列。

存储说明
m_fast_path_state用fast path方法获取的锁存在这里面
m_granted队列用slow path方法获取的锁存在这里面,在这之前需要先将fast path获取的锁从m_fast_path_state删除再存到这里面。这个用来存储表已经获取的锁。
m_waiting队列用slow path方法获取的锁存在这里面,这个用来存储表正在等待获取的锁。
类型说明
unobtrusiveS, SH, SR and SW,用m_fast_path_state计数,不保存具体锁信息。用fast path方法获取锁。用m_fast_path_state变量保存,不用m_granted队列保存锁
obtrusiveSU, SRO, SNW, SNRW, X,用slow path方法获取锁,用m_granted队列保存锁

二、MDL策略级别

mdl锁可以被申请条件:参考MDL_lock::can_grant_lock

  1. granted队列别的线程没有不兼容锁

  2. waiting队列没有更高等级的锁在等待

具体按照以下的矩阵表来选出mdl是否可以被申请,其中waiting策略有四个矩阵,这四个矩阵主要是为了防止低优先级的锁等待太久产生锁饥饿,因此按照锁类型的数量必要的时候进行等待锁策略升级,说明见以下。

策略矩阵说明
m_granted_incompatible以下第一个兼容图
m_waiting_incompatible[0]以下第二个兼容图
m_waiting_incompatible[1]获取的piglet锁数量超过max_write_lock_count
m_waiting_incompatible[2]获取的hog锁数量超过max_write_lock_count
m_waiting_incompatible[3]获取的piglet锁和hog锁总和数量超过max_write_lock_count
类型说明
独占型(hog)打算申请X, SNRW, SNW,别的锁在等待; 具有较强的不兼容性,优先级高,容易霸占锁,造成其他低优先级锁一直处于等待状态。m_hog_lock_count统计表申请到的hog类型锁
暗弱型(piglet)打算申请SW,SRO在等待; SW优先级仅高于SRO。m_piglet_lock_count统计表申请到的piglet类型锁
类型说明
S共享锁,读元数据,不读表数据,比如create table t1 like t2
SH和S一样,读元数据,但优先级比排他锁高。如DESCt
SR读元数据,且读表数据,如事务中select rows
SW读元数据,且更新表数据,如事务中update rows
SWLP优先级低于SRO,DML时加LOW_PRIORITY
SU可升级锁,允许并发读写表数据。可读元数据,及读表数据。可以升级到SNW、SNR、X锁。用在alter table的第一阶段,不阻塞DML,防止其他DDL
SRO只读锁,可读元数据,读表数据,但不可DDL和修改数据。如lock table read
SNW读元数据及表数据,阻塞他人修改数据,可升级到X锁。用在ALTER TABLE第一阶段,拷贝原始表数据到新表,允许读但不允许更新
SNRW读元数据,及读写数据,阻塞他人读写数据,例如lock table write
X排他锁,可以修改字典和数据,例如alter table

具体策略矩阵图:(以下+号代表可以被满足,-号代表不能被满足需要进入waiing队列等待)

grangted队列策略:m_granted_incompatible

请求类型已经申请到的lock(m_granted队列)
SSHSRSWSWLPSUSROSNWSNRWX
S+++++++++-
SH+++++++++-
SR++++++++--
SW++++++----
SWLP++++++----
SU+++++-+---
SRO+++--+++--
SNW+++---+---
SNRW++--------
X----------

waiting0队列策略:m_waiting_incompatible[0],正常申请时候waiting队列的矩阵

请求类型待完成lock(m_waiting队列)
SSHSRSWSWLPSUSROSNWSNRWX
S+++++++++-
SH++++++++++
SR++++++++--
SW+++++++---
SWLP++++++----
SU+++++++++-
SRO+++-++++--
SNW+++++++++-
SNRW+++++++++-
X++++++++++

waiting1队列策略:m_waiting_incompatible[1],使SW优先级比SRO低

请求类型待完成lock(m_waiting队列)
SSHSRSWSWLPSUSROSNWSNRWX
S+++++++++-
SH++++++++++
SR++++++++--
SW++++++----
SWLP++++++----
SU+++++++++-
SRO++++++++--
SNW+++++++++-
SNRW+++++++++-
X++++++++++

waiting2队列策略:m_waiting_incompatible[2],S, SH, SR, SW, SNRW, SRO and SU优先度比SNW、SNRW、X高

请求类型待完成lock(m_waiting队列)
SSHSRSWSWLPSUSROSNWSNRWX
S++++++++++
SH++++++++++
SR++++++++++
SW++++++++++
SWLP++++++-+++
SU++++++++++
SRO+++-++++++
SNW+++---+++-
SNRW++-----++-
X-------+++

waiting3队列策略:m_waiting_incompatible[3],优先选择 SRO 锁,而非 SW/SWLP 锁。此外,除 SW/SWLP 之外,非“hog”锁优先于“hog”锁。

请求类型待完成lock(m_waiting队列)
SSHSRSWSWLPSUSROSNWSNRWX
S++++++++++
SH++++++++++
SR++++++++++
SW++++++----
SWLP++++++----
SU++++++++++
SRO++++++++++
SNW+++++-+++-
SNRW++-++--++-
X---++--+++

三、策略升级对实际执行的影响

当有多线程多资源在抢同一张表的锁资源的时候,如果想要低优先级的锁先得到授权,那么可以通过修改系统变量max_write_lock_count来实现目的。下面通过2个例子来看看修改max_write_lock_count如何影响多线程的锁等待动作。

首先创建一张表。

greatsql> CREATE TABLE `t20` (
  `s1` int NOT NULL,
  `s2` varchar(100) DEFAULT NULL,
  `s3` timestamp(3) NULL DEFAULT NULL,
  `i` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`s1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

greatsql> INSERT INTO t2 VALUES (1,'aaaa','2021-01-19 03:14:07.123'),(2,null,'2022-01-19 03:14:07.123'),(3,'bbbb',null),(4,null,null),(15,'cccc','2025-01-19 03:14:07.123');

1、max_write_lock_count设置为100

SET GLOBAL max_write_lock_count=100; 打开6个session进行实验。分别敲入以下SQL命令。因为m_piglet_lock_count<max_write_lock_count因此以下的6个session都是执行waiting的策略0。

session 1session 2session 3session 4session 5session 6
begin;
update t20 set i=15 where s1=15;
lock table t20 read; 卡住
lock table t20 read; 卡住
update t20 set i=15 where s1=15;卡住
lock table t20 read; 卡住
update t20 set i=15 where s1=15;卡住
session 1session 2session 3session 4session 5session 6
锁状态SHARED_WRITE获取SHARED_READ_ONLY等待;SHARED_READ_ONLY等待SHARED_WRITE获取,虽然看到sql卡住,但是超时会主动报错。这里卡住是被innodb的行锁控制了SHARED_READ_ONLY等待;SHARED_WRITE等待

接着第一个session执行commit,观察一下后面几个session锁的变化,可以看到最后一个session的SW锁因为实行的是策略0因此commit之后按照SW优先度比SRO高获取到了SW锁。

session 1session 2session 3session 4session 5session 6
begin;
update t20 set i=15 where s1=15;
lock table t20 read; 成功
lock table t20 read; 成功
update t20 set i=15 where s1=15;成功
lock table t20 read; 成功
update t20 set i=15 where s1=15;成功
commit
session 1session 2session 3session 4session 5session 6
锁状态SHARED_READ_ONLY获取;SHARED_READ_ONLY获取;SHARED_WRITE获取SHARED_READ_ONLY获取;SHARED_WRITE获取

2、max_write_lock_count设置为1

SET GLOBAL max_write_lock_count=1; 这里在执行完session4的时候因为m_piglet_lock_count>=max_write_lock_count,因此进行了一次waiting策略升级,升级为了策略1。

session 1session 2session 3session 4session 5session 6
begin;
update t20 set i=15 where s1=15;
lock table t20 read; 卡住
lock table t20 read; 卡住
update t20 set i=15 where s1=15;卡住。这里转换为waiting策略1
lock table t20 read; 卡住
update t20 set i=15 where s1=15;卡住
session 1session 2session 3session 4session 5session 6
锁状态SHARED_WRITE获取SHARED_READ_ONLY等待;SHARED_READ_ONLY等待;SHARED_WRITE获取SHARED_READ_ONLY等待;SHARED_WRITE等待

接着第一个session执行commit释放SHARED_WRITE锁,可以看到最后一个session的SW锁应该在策略1优先度比SRO低,因此还处于等待状态。而在之前第一个例子里,因为实行的是策略0因此commit之后最后一个session因为优先度比SRO高因此获取到了SW锁。

在session5的SRO获取到锁以后,因为已经没有SRO锁在等待了,因此进行了一次waiting策略降级,重新降级为了0。

session 1session 2session 3session 4session 5session 6
begin;
update t20 set i=15 where s1=15;
lock table t20 read; 成功
lock table t20 read; 成功
update t20 set i=15 where s1=15;成功。
lock table t20 read; 成功。这里转换为waiting策略0
update t20 set i=15 where s1=15;继续等待
commit
session 1session 2session 3session 4session 5session 6
锁状态SHARED_READ_ONLY获取SHARED_READ_ONLY获取SHARED_WRITE获取SHARED_READ_ONLY获取SHARED_WRITE继续等待。

用命令查看一下锁状态

greatsql> SELECT * FROM performance_schema.metadata_locks where object_schema='db1' and object_name='t20';
+-------------+---------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| 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       | db1           | t20         | NULL        |       140733798645792 | SHARED_READ_ONLY | TRANSACTION   | GRANTED     | sql_parse.cc:6723 |              73 |             20 |
| TABLE       | db1           | t20         | NULL        |       140733664568448 | SHARED_READ_ONLY | TRANSACTION   | GRANTED     | sql_parse.cc:6723 |              56 |             22 |
| TABLE       | db1           | t20         | NULL        |       140733327666736 | SHARED_READ_ONLY | TRANSACTION   | GRANTED     | sql_parse.cc:6723 |              75 |             27 |
| TABLE       | db1           | t20         | NULL        |       140733396820960 | SHARED_WRITE     | TRANSACTION   | PENDING     | sql_parse.cc:6723 |              77 |              9 |
+-------------+---------------+-------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
# 最后一个session的SW锁在等待

3、锁改变策略时机

锁唤醒时机,参考MDL_lock::reschedule_waiters:

锁唤醒时机
从granted或者waiting队列remove_ticket
别的线程申请锁的时候进行waiting策略升级
别的线程锁释放
别的线程锁降级

可以看到上面的例子就是在commit以后执行了锁唤醒才导致了策略升级,于是产生了跟第一个例子不同的结果。

四、总结

实际生产中如果在多个线程抢同一张表的锁资源的时候,如果想要低优先级的锁优先获得锁,可以尝试修改系统变量max_write_lock_count,改小可以防止锁饥饿,但是可能会影响别的线程正在执行的业务,因此也要谨慎使用。当然如果想要高优先级锁先获得锁也可以改大max_write_lock_count值,看具体业务需求。

Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

image

社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html

社区博客有奖征稿详情: https://greatsql.cn/thread-100-1-1.html

(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)

技术交流群:

微信&QQ群:

QQ群:533341697

微信群:添加GreatSQL社区助手(微信号:wanlidbc )好友,待社区助手拉您进群。

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

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

相关文章

基于tinymce实现多人在线实时协同文本编辑

基于tinymce实现多人在线实时协同文本编辑 前言 这可能是最后一次写tinymce相关的文章了&#xff0c;一方面tinymce的底层设计限制了很多功能的实现&#xff0c;另一方面tinymce本身越来越商业化&#xff0c;最新的7版本已经必须配置key&#xff0c;否则面临无法使用的问题。…

PPT如何添加水印?推荐两种方法!

在PPT演示文稿中添加水印&#xff0c;可以有效地保护版权或在背景上增加品牌标识。本文将介绍两种在PPT中添加水印的方法&#xff0c;帮助你轻松实现这一功能&#xff0c;一起来看看吧&#xff01; 方法一&#xff1a;在单张幻灯片上添加水印 1、选择目标幻灯片 打开PPT文件&…

防近视台灯有效果吗?学生家长们应该了解护眼台灯怎么选

在当前社会&#xff0c;近视的影响不容小视&#xff0c;除了对视觉健康的影响外&#xff0c;近视还可能对个人的心理健康产生负面影响。视力不佳可能导致自卑感和社会交往障碍&#xff0c;尤其是在儿童和青少年时期。保护视力健康要从小做起&#xff0c;家长们可以关注孩子的用…

【原创教程】电气电工07:网线的制作方法

电气电工经常会遇到做网线,我们做网线需要网线钳与测试仪。需要了解网线的两种接线标准。 我们来看一下网线钳的操作步骤: 这种压线钳也同时具有剥线、剪线功能。 用这种网线钳能制作RJ45网络线接头。RJ11电话线接头、4P电话线接头。适用于RJ45,RJ11型网线 做网线的时候我…

npm安装时一直在idealTree:npm: sill idealTree buildDeps卡住不动解决方法

npm安装xmysql时一直idealTree:npm: sill idealTree buildDeps卡住不动 问题解决&#xff0c;如下图所示 解决方法&#xff1a; 1、查看.npmrc位置&#xff0c;并去目录中删掉.npmrc文件 --在cmd&#xff08;DOS页面&#xff09;界面执行下述指令&#xff0c;可查看 .npmrc 文…

需要频繁查询的文档+索引命名规则

1.规则及样例 规则_S_00_R_240821.1_文档编号推荐命名规则V1.0.txt 模板_T_HV_C_248021.1_传感器及采集器IP分配表V1.0.xlsx 重要的需要频繁参考的文档纳入4段式文档编号体系&#xff1a;文档编号由四段组成&#xff1a; X_XX_X_XXXXXX.X T.........模板Template【其他还有&am…

自抗扰控制ADRC原理解析及案例应用

1. ADRC基本原理 1.1 ADRC的基本概念 自抗扰控制&#xff08;Active Disturbance Rejection Control&#xff0c;ADRC&#xff09;是一种先进的控制策略&#xff0c;由韩京清研究员于1998年提出。ADRC的核心思想是将系统内部和外部的不确定性因素视为总扰动&#xff0c;并通过…

AtCoder Beginner Contest 367 A~F

A.Shout Everyday&#xff08;枚举&#xff09; 题意&#xff1a; 在 A t C o d e r AtCoder AtCoder 王国&#xff0c;居民们每天都要在 A A A 点大声喊出他们对章鱼烧的热爱。 住在 A t C o d e r AtCoder AtCoder 王国的高桥每天 B B B 点睡觉&#xff0c; C C C 点…

day17:一文弄懂“无参装饰器”、“有参装饰器”和“叠加装饰器”

目录 一、无参装饰器1. 什么是装饰器2. 为何要用装饰器3. 如何用解决方案一&#xff1a;失败&#xff0c;优化见↓↓↓解决方案二&#xff1a;失败&#xff0c;优化见↓↓↓解决方案三&#xff1a;失败&#xff0c;优化见↓↓↓方案三的优化一&#xff1a;将index的参数写活了方…

重磅发布!天途多自由度无人机调试台

无人机调试、测试和试飞很容易受空域、场地、环境、失控炸机和操作失误等限制。天途TE55多自由度无人机整机调试台应运而生&#xff01; 突破空域限制 天途TE55多自由度无人机整机调试台&#xff0c;突破场地空域限制&#xff0c;不到0.7平米的空间&#xff0c;即可完成小型无人…

[数据集][目标检测]建筑工地楼层空洞检测数据集VOC+YOLO格式2588张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2588 标注数量(xml文件个数)&#xff1a;2588 标注数量(txt文件个数)&#xff1a;2588 标注…

基于vue框架的办公用品管理系统i52wc(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;部门,员工,办公用品,入库记录,出库记录,申领信息 开题报告内容 基于Vue框架的办公用品管理系统 开题报告 一、引言 随着企业规模的扩大和日常运营的复杂化&#xff0c;办公用品的管理成为了一个不容忽视的重要环节。传统的办公用品管…

Java中接口

接口的定义和使用 练习 public abstract class Animal {private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this.name…

ChatGPT、Claude 和 Gemini 在数据分析方面的比较(第 2 部分)

欢迎来到雲闪世界。欢迎回到我的系列文章的第二部分&#xff0c;ChatGPT、Claude 和 Gemini 在数据分析方面的比较&#xff01;在本系列中&#xff0c;我旨在比较这些 AI 工具在各种数据科学和分析任务中的表现&#xff0c;以帮助其他数据爱好者和专业人士根据自己的需求选择最…

告别图片堆成山, 图片转pdf工具:你的整理小能手来啦!

嘿&#xff0c;各位小伙伴&#xff01;你们有没有觉得&#xff0c;现在拍照比吃饭还日常&#xff0c;手机、电脑里堆满了照片&#xff0c;找起来简直跟大海捞针似的&#xff1f;别急&#xff0c;我今儿个就来给你们支个招——图片转PDF大法&#xff0c;一键变成整整齐齐的PDF文…

【Java-异常】

异常&#xff1a;程序在运行期间产生的一些错误 Java通过API中Throwable类的众多子类描述各种不同的异常。Java异常都是对象&#xff0c;是Throwable子类的实例。 Throwable可以划分为两个大类&#xff1a; Error错误类&#xff1a;会导致JVM虚拟机宕机 Exception异常类&…

Java---二维数组

一.数组的维数 假象&#xff1a;一维数组 二维数组&#xff1a;数组中的元素是一维数组 二.五子棋游戏 import javax.swing.*;public class Array06 {static String[][] matrix new String[15][15];static String black "⚫";static String white "⚪"…

SQL进阶技巧:多维分析之如何还原任意维度组合下的维度列簇名称?【利用grouping_id逆向分析】

目 录 0 需求描述 1 数据准备 2 问题分析 3 小结 0 需求描述 现有用户访问日志表 visit_log ,每一行数据表示一条用户访问日志。 需求: (1)按照如下维度组合 (province), (province, city), (province, city, device_type) 计算用户访问量,要求一条SQL语句统计所所…

[000-01-018].第3节:Linux环境下ElasticSearch环境搭建

我的后端学习笔记大纲 我的ElasticSearch学习大纲 1.Linux系统搭建ES环境&#xff1a; 1.1.单机版&#xff1a; a.安装ES-7.8版本 1.下载ES: 2.上传与解压&#xff1a;将下载的tar包上传到服务器software目录下&#xff0c;然后解压缩&#xff1a;tar -zxvf elasticsearch-7…

logstash入门学习

1、入门示例 1.1、安装 Redhat 平台 rpm --import http://packages.elasticsearch.org/GPG-KEY-elasticsearch cat > /etc/yum.repos.d/logstash.repo <<EOF [logstash-5.0] namelogstash repository for 5.0.x packages baseurlhttp://packages.elasticsearch.org…