MySQL添加索引时会锁表吗?

目录

  • 简介
  • Online DDL概念
  • Online DDL用法
  • 总结

简介

在MySQL5.5以及之前的版本,通常更改数据表结构操作(DDL)会阻塞对表数据的增删改操作(DML)。
MySQL5.6提供Online DDL之后可支持DDL与DML操作同时执行,降低了DDL期间对业务延迟带来的影响。

下面进行案例演示。我们准备了一个分数表,有600万的测试数据,接下来我们验证一下我们日常使用的ALTER语句(不提交),看看是否会全程锁表

#事务A 添加索引 不提交
begin;
ALTER TABLE scores ADD index idx_student_id (student_id);
# commit;
#事务B 查询数据与修改数据
begin;
select id from scores where id= 1;
commit;begin;
update scores set course_name = '张三' where id = 1;
commit;

发现查询事务和修改事务都是可以正常返回的,发现这条DDL语句不会全程锁表,执行过程中真的不会锁表吗?我们再看一种情况,首先删除索引:

ALTER TABLE scores drop index idx_student_id;

然后开启添加索引事务(不提交),然后再开启查询事务,并且也不提交,这个时候通过show processlist命令查看mysql的执行信息,观察加索引时ddl语句的执行情况。

show processlist;

观察到ddl语句正在执行中:

在这里插入图片描述

再show一下,发现ddl语句变成了等待我们的元数据锁释放中,即查询语句持有了我们的一个元数据锁。这个时候我们提交查询事务,可以发现索引就添加成功了。说明我们这条sql本质上还是有个加锁的过程。

在这里插入图片描述

再看一种情况,也先删除索引,然后开启查询事务不提交,去持有元数据锁,然后再执行添加索引,然后show一下执行信息,发现DDL语句已经在等待元数据锁释放了。然后我们提交一下查询事务,再show一下,发现DDL语句正在往下执行,这个时候我们再开启一个事务进行修改(也不提交),多show几下直到DDL执行完毕,发现我们开启的修改事务阻塞了我们的DDL语句继续执行。提交修改事务,发现索引就添加成功了。那么也就是说我们这个DDL语句实际上有两个加锁的过程,并且在这个加锁的时候如果说我们的元数据锁被其他的事务给占有了,那么我们这个DDL语句就会被阻塞,第二次也是一样的。

MySQL 5.6或更高版本上进行表结构修改操作(如添加索引),MySQL默认情况下会尝试使用Online DDL来最小化操作对读写操作的影响,MySQL会选择默认的最佳方式进行操作。



Online DDL概念

概念:在不中断现有数据读写操作的情况下,自动执行 DDL语句(例如创建、修改、删除表等)的机制。Online DDL 可以在MySQL进行表空间或数据文件的变化时,自动执行 DDL语句,从而避免了传统方式中,执行 DDL 语句时对数据库读写操作的干扰和中断。

执行过程:Online ddl 执行大致可分为三个阶段:初始化阶段、执行阶段和提交表定义阶段:

  • 初始化阶段:
    • 评估存储引擎能力与DDL语句
    • 评估ALGORITHM 和 LOCK
    • 创建可升级的MDL读锁(元数据读锁)
  • 执行阶段:
    • 此阶段分为两个步骤准备和执行DDL语句
    • 此阶段是否需要MDL写锁取决于初始化阶段评估的因素。如果需要MDL写锁的话,仅在准备过程会短暂的使用MDL写锁,然后降级为MDL读锁
    • DDL执行过程(最耗时)
  • 提交表定义阶段:
    • 此阶段会将MDL读锁升级到MDL写锁,此阶段一般较快,因此独占锁的时间也较短
    • 用新的表定义替换旧的表定义,释放MDL锁

Online DDL用法

区别与我们日常使用的DLL语句,多了两个参数

ALTER TABLE scores ADD index idx_student_id (student_id) , ALGORITHM=INPLACE, LOCK=NONE;ALTER TABLE scores ADD index idx_student_id (student_id) , ALGORITHM=COPY, LOCK=EXCLUSIVE;

ALGORITHM有三个可选项

ALGORITHM=DEFAULT:默认算法,使用最高效的算法


ALGORITHM=INPLACE:解决全程锁表的一个方式,在原表上进行更改,不需要生成临时表,不需要进行数据copy的过程。
添加索引步骤:
1.创建索引(二级索引)数据字典
2.加共享表锁,禁止DML,允许查询
3.读取聚簇索引,构造新的索引项,排序并插入新索引
4.等待打开当前表的所有只读事务提交
5.创建索引结束


ALGORITHM=COPY:最原始的方式,通过临时表创建索引,需要多一倍存储,还有更多的I0(类似5.6版本之前的处理过程)添加索引步骤:
1.新建带索引(主键索引)的临时表心
2.锁原表,禁止DML,允许查询
3.将原表数据拷贝到临时表
4.禁止读写,进行rename,升级字典锁
5.完成创建索引操作

LOCK有四种

LOCK=DEFAULT:默认方式,MySQL自行判断使用哪种LOCK模式,尽量不锁表
LOCK=NONE:无锁:允许Online DDL期间进行并发读写操作。通常与INPLACE搭配使用。如果Online DDL操作不支持对表的继续写入,则DDL操作失败,对表修改无效
LOCK=SHARED:共享锁:Online DDL操作期间堵塞写入,不影响读取
LOCK=EXCLUSIVE:排它锁:Online DDL操作期间不允许对锁表进行任何操作

接下来我们使用这两种执行方式来看一下是不是会全程锁表。先是第一种的INPLACE:

ALTER TABLE scores ADD index idx_student_id (student_id) , ALGORITHM=INPLACE, LOCK=NONE;

先删除刚刚的索引,然后开启一个事务添加索引(不提交),执行一下查询事务(提交),是可以正常查询的。再开启一个修改事务(提交),是可以正常修改的。即,INPLACE方式是不会全程锁表的。那么它在执行的过程中会加锁吗?

还是删除索引,然后开启一个事务添加索引(不提交),执行一下查询事务(不提交),此时show一下执行信息,发现DDL语句正在执行ALTER语句,再show一下,发现DDL语句已经被阻塞了,因为它在等待元数据锁释放,也就是说,DDL语句实际上还是会有个加锁的过程。提交一下查询事务,发现索引就添加成功了。

然后我们再次验证一种场景,还是删除索引,然后先开启一个查询事务(不提交)先持有元数据锁,然后再开启事务添加索引(不提交),这个时候show一下执行信息,发现DDL语句正在等待元数据锁释放,提交一下查询事务,show一下发现ddl语句正在往下执行,这个时候再开启一个修改事务(不提交),多show几下直到DDL执行完毕,发现我们的DDL语句也被这个修改事务阻塞了,因为它正在等待元数据锁的释放,这个时候我们再开一个修改事务(提交)、查询事务(提交),show一下发现他们都被阻塞住。也就是说online ddl语句被阻塞后它就会进一步的将后续过来的DML事务全部阻塞住,将修改事务提交,索引就添加成功了。

所以日常使用的DDL语句的INPLACE方式执行过程有两次加锁,加锁过程中如果有其他事务持有了元数据锁,DDL语句就会被阻塞,后续来的DML操作都会被阻塞住。

再看一下COPY方式:

ALTER TABLE scores ADD index idx_student_id (student_id) , ALGORITHM=COPY, LOCK=EXCLUSIVE;

还是删除索引,然后开启一个事务添加索引(不提交),然后执行查询事务(提交),修改事务(提交),执行信息发现两个DML语句都被阻塞。即COPY方式是全程锁表的,它不允许DDL和DML的并发。

总结

从宏观上看,Online DDL的事务相当于会和其他事务并行执行,只不过Online DDL会在表空闲时进行执行,所以Online DDL不会阻塞其他操作,在Online DDL执行过程会两次获取MDL锁(1.申请MDL写锁 2. 降级成MDL读锁 3.执行DDL --耗时 4. 升级MDL写锁 5. 释放MDL锁),并且需要等待已经持有MDL锁的并发事务提交或回滚后才能继续执行,在实际执行时需注意以下几点:

  • 进行DDL操作时尽量在业务低峰期进行操作。尽量的降低我们online ddll的阻塞时间,进而减少整个表的死锁
  • 在操作之前最好确认对要操作的表没有任何进行中的操作、没有未提交事务、也没有显式事务中的报错语句。
  • 设置超时时间lock_wait_timeout,避免长时间的metedata锁等待。
set global lock_wait_timeout = 60;
# 单位是s 默认好像是一年show variables like '%timeout%';

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

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

相关文章

【Vue】深入了解 Axios 在 Vue 中的使用:从基本操作到高级用法的全面指南

文章目录 一、Axios 简介与安装1. 什么是 Axios?2. 安装 Axios 二、在 Vue 组件中使用 Axios1. 发送 GET 请求2. 发送 POST 请求 三、Axios 拦截器1. 请求拦截器2. 响应拦截器 四、错误处理五、与 Vuex 结合使用1. 在 Vuex 中定义 actions2. 在组件中调用 Vuex acti…

免费【2024】springboot OA公文发文管理系统

博主介绍:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围:SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

VScode+latex+Sumatra 环境配置

目录 安装Tex Live 及Vscode 安装Tex Live 及Vscode 此处参考博客:VScodelatexSumatra PDF环境配置(步步到位)进行安装。 本文主要记录配置的json文件设置。 {"latex-workshop.latex.autoBuild.run": "never","la…

js 实现扫雷游戏,源码开放,支持npm引入使用

本人开发的js版本扫雷游戏 体验地址 | Github Minesweeper game Sponsors Install and use npm i minesweeper-gameimport {Map} from minesweeper-game;const map new Map();Reset Map map.reset();TS Statement interface IMapOptions {width?: number; // Map sizeh…

Clickhouse 物化视图-optimize无效

select a, b from test_all; 优点 空间换时间:查询速度快 CREATE MATERIALIZED VIEW test_mv ON CLUSTER ENGINEReplicatedReplacingMergeTree partition by toYYYYMM(b) ORDER BY (b) AS select a, b from test_all where a ! 1; select a, b from test_mv 会看…

[ptrade交易实战] 第十七篇 期货交易类函数!

前言 今天给大家分享的是期货交易相关里面的期货交易函数,这一类的函数是相对较少,可以一次性讲完! 具体的开通渠道可以看文章末尾! 一、buy_open —— 多开 buy_open(contract, amount, limit_priceNone) 买入开仓函数 注意…

数据实时获取方案之Flink CDC

目录 一、方案描述二、Flink CDC1.1 什么是CDC1.2 什么是Flink CDC1.3 其它CDC1.4 FlinkCDC所支持的数据库情况 二、使用Pipeline连接器实时获取数据2.1 环境介绍2.2 相关版本信息2.3 详细步骤2.3.1 实时获取MySQL数据并发送到Kafka2.3.2 实时获取MySQL数据并同步到Doris数据库…

如何使用fiddler 查看手机端数据包

要使用Fiddler查看手机端的数据包,可以按照以下步骤进行操作: 下载并安装Fiddler:首先需要在你的电脑上下载并安装Fiddler软件。可以在Fiddler官方网站(https://www.telerik.com/fiddler)上找到适合你操作系统的版本&a…

初识C++|模板初阶

🍬 mooridy-CSDN博客 🧁C专栏(更新中!) 目录 🍉1. 泛型编程 🍉2. 函数模板 🥝2.1 函数模板概念 🥝2.2 函数模板格式 🥝2.3 函数模板的原理 &#x1f95…

万界星空科技QMS系统:全面赋能企业质量管理的创新引擎

万界星空科技质量管理QMS系统(Quality Management System)是一套全面、高效的质量管理工具,旨在帮助企业提升产品质量、优化生产流程、降低质量成本。该系统集成了多个功能模块,以满足企业在质量管理方面的各种需求。以下是万界星…

【网络安全科普】勒索病毒 防护指南

勒索病毒简介 勒索病毒是一种恶意软件,也称为勒索软件(Ransomware),其主要目的是在感染计算机后加密用户文件,并要求用户支付赎金以获取解密密钥。这种类型的恶意软件通常通过电子邮件附件、恶意链接、下载的软件或漏洞…

Android --- Kotlin学习之路:协程的使用,什么是协程,为什么要用协程?(学习笔记)

Kotlin 协程(coroutine)学习 以下干货满满,掌握以下内容一定会对你在项目开发中有所帮助,记得收藏!!! 文章目录 什么是协程,为什么要用协程?挂起函数挂起的是什么&#…

Svelte与Vue:框架性能与设计理念的比较

Svelte 和 Vue.js 都是现代前端框架,旨在简化 Web 开发并提高应用程序的性能。虽然它们都提供了构建用户界面的工具,但在设计理念、编译过程、运行时开销和性能方面存在显著差异。 Svelte 框架的特点 Svelte 的核心理念是在构建阶段尽可能多地完成工作…

JavaWeb JavaScript ① JS简介

目录 一、HTML&CSS&JavaScript的作用 二、前后端关联标签——表单标签 1.form标签 2.input标签 3.get/post提交的差异 4.表单项标签 5.布局相关标签 块元素——div 行内元素——span 三、CSS 1.CSS引入方式 方式1 行内式 方式2 内嵌式 方式3 外部样式表 2.CSS选择器 元…

【c++】用c++类做一个猜数字游戏

目录 源码: 想法: 可以改进的地方: 源码: #include<iostream> #include<ctime> #include<cstdlib> #include<string>using std::cout; using std::endl; using std::cin;class player { private:int card;bool viewable; public:player(): card…

Java基础编程500题——String

&#x1f4a5; 该系列属于【Java基础编程500题】专栏&#xff0c;如您需查看Java基础的其他相关题目&#xff0c;请您点击左边的连接 目录 1. 将字符串"Hello World"中的所有小写字母转换成大写字母。 2. 将两个字符串"Hello"和"World"拼接。 …

Zabbix监控介绍与部署

目 录 一、zabbix介绍和架构 1.1 zabbix介绍 1.2 为什么需要监控 1.3 需要监控什么 二、zabbix使用场景与系统概述 2.1 zabbix的功能 2.2 zabbix架构 2.3 Zabbix术语 三、编译安装zabbix 3.1 安装依赖环境 3.2 建立管理用户 3.3 准备源码包&#xff0c;解压包 3.…

082、Python 读文本文件

在Python中读取txt文本文件可以通过内置的open()函数结合file对象的read(), readline(), readlines()等方法实现。 1. 使用read()方法 read()方法会读取文件的全部内容&#xff0c;并将其作为一个字符串返回。 # 打开文件并读取全部内容with open(Resources/雨巷.txt, r, en…

Vue中Key的作用

在Vue中&#xff0c;Key的作用主要体现在以下几个方面&#xff1a; 1. 唯一标识列表元素 Key是Vue中用于唯一标识列表元素的特殊属性。在使用v-for指令渲染列表时&#xff0c;每个列表项都应该拥有唯一的key&#xff0c;这样Vue就能准确地追踪每个节点的身份&#xff0c;从而…

linux中当前目录、上级目录、上上级目录表示方法

1&#xff0c;cd [目录名]&#xff1a;表示进入某个目录 . &#xff1a;代表当前的目录&#xff0c;也可以使用 ./ 来表示&#xff1b;(一个点表示当前目录) . . &#xff1a;代表上一层目录&#xff0c;也可以 ../ 来代表。(两个点表示当前目录的上一层目录) ../..…