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. Angular开发者指南(三)数据绑定

    数据绑定 AngularJS应用程序中的数据绑定是模型和视图组件之间的数据的自动同步. AngularJS实现数据绑定的方式可以将模型视为应用程序中的单一来源. 视图是模型在任何时候的投影. 当模型更 ...

  2. 微信中的APP、公众号、小程序的openid及unionid介绍

    微信中的APP.公众号.小程序的openid及unionid介绍 1.unionid 如果开发者拥有多个移动应用.网站应用.和公众帐号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只 ...

  3. 74cms_3.5.1 宽字节注入

    第一次进行CMS的代码审计,我选择了2014年发布的74CMS 3.5.1,历史比较久远的CMS往往存在更多的问题,虽然技术上难度不大,但是在思路方面给了我很大的启发.下面我根据我的思路给大家分享一下 ...

  4. Java多线程处理任务(摘抄)

    很多时候,我们需要对一个庞大的队列或者二维数组进行处理.这些处理可能是循环的,比如给一个excel多个sheet的联系人列表发邮件.很幼稚的方法就是用一个或者两个FOR循环搞定,对于庞大的数据有得让你 ...

  5. Apsara Clouder云计算专项技能认证:网站建设-部署与发布

    一.课程学习介绍和学习目标 1.学习内容 掌握如何将一个本地已经设计好的静态网站发布到Internet公共互联网,通过自己的域名让全世界的网民访问到,如何完成工信部的ICP备案,实现监管合规. 2.学 ...

  6. 基础_1:RCP基本框架

    Display: Display是一个SWT对象,代表底层图形系统的实现.一个RCP应用程序只需要一个Display对象. Display的主要任务是从操作系统队列中读取事件,传递给RCP的事件监听器 ...

  7. 结构体struct,类class

    1.struct,值类型,结构体会自动生成初始化方法,class是引用类型 struct Person { var name : String var age : Int func simpleDes ...

  8. MOOC(7)- case依赖、读取json配置文件进行多个接口请求-读取json封装成类(13)

    把读取json数据的函数封装成类 # -*- coding: utf-8 -*- # @Time : 2020/2/12 16:44 # @File : do_json_13.py # @Author ...

  9. SHELL用法九(awk练习)

    1.SHELL编程Awk语句案例实战 Awk主要是用于对文本文件进行处理,通常是逐行处理,其语法参数格式为, AWK常用参数.变量.函数详解如下: awk 'pattern + {action}' f ...

  10. Linux下MongoDB的部署

    一.MongoDB的下载解压 MongoDB在linux是免编译安装的,直接解压就可以用. # 解压 tar -zxvf mongodb-linux-x86_64-3.0.6.tgz # 将解压包拷贝 ...