0.前言

MySQL按照加锁的范围,分为全局锁、表级锁、行级锁。

本文作为上篇,主要介绍MySQL的全局锁 和 表级锁。

重要的实战总结为,如何安全地变更一个表的表结构。

1.全局锁

定义:

全局锁就是对整个数据库实例加锁。

全局锁语法:

Flush tables with read lock (FTWRL)

当你使用这个命令后,整个库处于只读状态,之后其他线程的数据更新语句(DML)、数据定义语句(DDL)都会被阻塞。

场景:不支持事务的引擎(如MyISAM),做全库的逻辑备份。

不过我们一般使用innodb,这个锁不太会接触,就不展开详细介绍了。

2.表级锁

表级锁其实有两种,一种叫表锁,一种叫原数据锁(meta data lock, MDL)

2.1 表锁

表锁的语法是:

锁表:lock tables … read/write

释放锁: unlock tables 主动释放锁

表锁也能够在客户端断开的时候自动释放。

值得注意的是,lock tables 除了会限制别的线程的读写外,当前线程接下来的操作也会被限制。

同样的,对于innoDB这种支持行锁的引擎,我们一般也不会去使用用表锁,因此,这部分内容也只需要简单了解下即可。

2.2 MDL锁

原数据锁meta data lock 也是一种表级锁,在 MySQL 5.5 版本中引入。

当我们对一个表做CRUD操作的时候,会加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

MDL读写锁的互斥

  • 读锁之间不互斥,所以我们可以有多个线程同时对一张表增删改查。
  • 读锁和写锁之间、写锁和写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,只要有一个线程要对一个表加字段,那天其他线程必须等这个线程完成表结构变更以后才能执行。

看到这里,不得不给大家举例一个日常会踩的坑。

对于大表DDL,大家一般比较谨慎,而对于小表,就会比较随意。但是小表DDL也能造成数据库崩溃。

Session A第一个启动,开启事务,select后没有立刻commit,模仿一个长事务,此时,session A对表tt的MDL读锁还没有释放。

Session B之后执行一个select,由于MDL读锁之间不互斥,因此执行成功。

Session C之后想对表tt 执行一个alter语句,需要获得MDL写锁,但是由于Session A持有了MDL读锁,读写锁互斥,因此Session C被阻塞。

Session D这时候也想执行一个select,由于Session C被阻塞,所以Session D也会被阻塞。

所以这个时候,后续的线程就都无法读写了。

如果接下来这个表上有频繁的查询,而且客户端有重试机制,那么超时后会再起一个新的session来查询,很快数据库的线程就溢出了。

这里有几个小问题需要稍微再解释一下:

1)从Session A的情况我们得知,事务中 的MDL锁,在语句开始时申请,但是并不是在语句结束后马上释放的,而是在整个事务提交后才会释放。

2)SessionC(DDL操作)被前面的SessionA和B(查询操作,获取MDL 读锁)所阻塞,这里实际上并没有成功获取MDL写锁,为什么Session D的读操作会被sessionC所阻塞呢?这里的原因是,MySQL Server端,对于Session C和Session D会有一个队列来决定谁先执行。

看到这里,我相信肯定有对MySQL比较熟悉的朋友会问了,MySQL 5.6不是号称支持Online DDL吗?怎么这里又会有各种阻塞呢?

首先,我们先明确下什么叫做Online DDL。

Online DDL的过程中,对于锁的获取分为五步(具体online DDL过程比较复杂,本文不展开说明):

1)拿到MDL写锁

2)降级成MDL读锁

3)真正做DDL

4)升级成MDL写锁

5)释放MDL锁

1、2、4、5如果没有锁冲突,执行时间都是非常短的。绝大部分时间是第三步占用了,而这个期间,表可用正常读写,所以被称为Online DDL。

而我们上文的例子,实际上是在第一步就阻塞了。

3.So,如何做一次安全的表结构变更

其实,无论大表小表的表结构变更,都应用引起我们重视。

总结了上文,大家应该都知道了最关键的三点:

避免长事务!

避免长事务!

避免长事务!

尤其是在执行表结构变更前,可以在information_schema库的innodb_trx表中,查看当前执行的事务。如果有长事务正在执行,要延迟等待执行变更,或者手动先kill长事务。

另外,尽量保证表结构变更在数据库流量低峰期操作,比如夜间,这样能更好地避免出现风险。

所以,如何做一次安全的表结构变更?

1)避免长事务

2)在流量低峰进行

就是这么简单。

下一期,我们就好好聊聊 行锁,不见不散~

参考:

丁奇《MySQL 实战45讲》

看到这里了,原创不易,点个关注、点个赞吧,你最好看了~

知识碎片重新梳理,构建Java知识图谱:https://github.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)

扫码关注我的公众号“阿丸笔记”,第一时间获取最新更新。同时可以免费获取海量Java技术栈电子书、各个大厂面试题。

前阿里数据库专家总结的MySQL里的各种锁(上篇)的更多相关文章

  1. 前阿里数据库专家总结的MySQL里的各种锁(下篇)

    在上篇中,我们介绍了MySQL中的全局锁和表锁. 今天,我们专注于介绍一下行锁,这个在日常开发和面试中常常困扰我们的问题. 1.行锁基础 由于全局锁和表锁对增删改查的性能都会有较大影响,所以,我们自然 ...

  2. 数据库性能测试---前阿里数据库团队资深DBA杨奇龙

    杨奇龙 前阿里数据库团队资深DBA 主要负责淘宝业务线,经历多次11.11,有海量业务访问DB架构设计经验. 目前就职于有赞科技DBA,负责数据库运维工作,熟悉MySQL 性能优化,故障诊断,性能压测 ...

  3. MySQL里面的锁

    MySQL里面的锁可以分为:全局锁,表级锁,行级锁. 一.全局锁:对整个数据库实例加锁.MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL)这个命令可以 ...

  4. 重新定义数据库的时刻,阿里云数据库专家带你了解POLARDB

    摘要:POLARDB是阿里云ApsaraDB数据库团队研发的基于云计算架构的下一代关系型数据库,其最大的特色是计算节点与存储节点分离,借助优秀的RDMA网络以及最新的块存储技术.POLARDB不但满足 ...

  5. 重新学习MySQL数据库10:MySQL里的那些日志们

    重新学习MySQL数据库10:MySQL里的那些日志们 同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志, ...

  6. jdbc连接阿里云服务器上的MySQL数据库 及 数据库IP限制

    问题1:Jdbc 如何连接阿里云服务器上的MySQL数据库? 解决: 上截图: 其中IP是阿里云服务器的公网IP地址. 问题2:   刚开始接手开发的时候,使用Navicat连接阿里云服务器上的数据后 ...

  7. mysql里的数据库引擎, 编码格式

    针对数据库里即使设置了varchar类型的字段, 值输入中文报错的情况,是因为数据库的默认编码类型不支持汉字输入. utf-8 可以编译全球通用的所有语言符号. 由1-6个可变字节组成,有非常严格的排 ...

  8. 使用Navicat连接阿里云服务器上的MySQL数据库=======Linux 开放 /etc/hosts.allow

    使用Navicat连接阿里云服务器上的MySQL数据库   1.首先打开Navicat,文件>新建连接> 2,两张连接方法 1>常规中输入数据库的主机名,端口,用户名,密码 这种直接 ...

  9. 云栖神侠传—阿里云数据库专家德歌告诉你PostgreSQL的那些事

    什么是云栖神侠传: 云栖社区(http://yq.aliyun.com/?utm_source=yqdg),是阿里云面向开发者群体的开放型社区.在云栖社区中,活跃着许多阿里技术大牛,他们在自己的技术领 ...

随机推荐

  1. nginx应用geoip模块,实现不同地区访问不同页面的需求(实践版)

    https://www.52os.net/articles/configure-nginx-using-geoip-allow-whitelist.html       搞了几天没有搞定,这篇文章一下 ...

  2. 吴裕雄--天生自然C语言开发:函数

    return_type function_name( parameter list ) { body of the function } /* 函数返回两个数中较大的那个数 */ int max(in ...

  3. Ubuntu虚拟环境的搭建

    转载:https://blog.csdn.net/weixin_43078957/article/details/86006240 虚拟环境的搭建1.pip install virtualenv这个要 ...

  4. ADB命令-1

    1.adb -s 指定设备号(用于已连接多个设备时) 2.adb install -r -t xxx 安装程序 3.adb pull  设备目录   本地目录 复制文件命令 4.adb push 向设 ...

  5. python--包package、模块module、类Class、Mixin类(未完成)

    包package>模块module>类Class(包含了属性.方法.实例等概念) 模式一:一个包下面有多个py文件,即多个模块module 模式二:一个包下面包含多个子包packages ...

  6. kafka + spark Streaming + Tranquility Server发送数据到druid

    花了很长时间尝试druid官网上说的Tranquility嵌入代码进行实时发送数据到druid,结果失败了,各种各样的原因造成了失败,现在还没有找到原因,在IDEA中可以跑起,放到线上就死活不行,有成 ...

  7. webpack中使用ECharts

    npm安装ECharts 引入ECharts 通过 npm 上安装的 ECharts 和 zrender 会放在node_modules目录下.可以直接在项目代码中 require('echarts' ...

  8. python多线程交替打印abc以及线程池进程池的相关概念

    import threading import sys import time def showa(): while True: lockc.acquire() #获取对方的锁,释放自己的锁 prin ...

  9. 吴裕雄--天生自然KITTEN编程:逃脱升天

  10. HEXO进阶打赏

    HEXO接近是最近有一些朋友提出的问题,然后我做了总结,如果你也在使用HEXO,不妨看看,应该会有些帮助. 1.博客部署样式出问题了怎么办? 2.电脑重装或者误删了本地博客怎么办? 3.想使用两台电脑 ...