1. 问题:怎么给线上表加字段?

工作中最常遇到的问题,怎么给线上频繁使用的大表添加字段?

比如:给下面的用户表(user)添加年龄(age)字段。

  1. CREATE TABLE `user` (
  2. `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  3. `name` varchar(100) DEFAULT NULL COMMENT '姓名',
  4. PRIMARY KEY (`id`)
  5. ) ENGINE=InnoDB COMMENT='用户表';

有同学会说,这还不简单,直接加不加完了,用下面的命令:

  1. ALTER TABLE `user` ADD `age` int NOT NULL DEFAULT '0' COMMENT '年龄';

添加完,再查看一下表结构:

  1. CREATE TABLE `user` (
  2. `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  3. `name` varchar(100) DEFAULT NULL COMMENT '姓名',
  4. `age` int NOT NULL DEFAULT '0' COMMENT '年龄',
  5. PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB COMMENT='用户表';

这不是添加成功了吗?有什么呀!

是的,线下数据库怎么整都行,但是如果在线上数据库这样操作,整个服务都有宕机的风险!自己也离毕业不远了。

不是危言耸听,我们找个case测试一下:

  1. Session1启动了一个事务,没有提交。
  2. Session2执行添加列的操作,被阻塞。
  3. 更严重的是,Session3执行简单查询的语句也被阻塞了。

2. 线上服务宕机的原因

为什么会出现这种情况呢?

原因是在执行查询语句的时候,MySQL自动加了MDL锁(metadata lock,即元数据锁)

不行的话,我们可以再执行一下show processlist命令,查看有哪些正在执行的进程:

可以清楚的看到Session2和Session3的语句正在等待MDL锁,Waiting for table metadata lock

MDL锁的作用是什么?

为了保证并发操作下数据的一致性。

如果一个事务正在执行中,另一个在这时修改了表结构,不但可能导致当前事务出现不可重复读的问题,还有可能连事务都无法提交。

什么时候会加MDL锁?

MDL锁是MySQL自动隐式加锁,无需我们手动操作。

在我们执行DDL语句的时候,MySQL自动添加MDL读锁。

在我们执行DML语句的时候,MySQL自动添加MDL写锁。

读锁与读锁之间不互斥,读锁与写锁、写锁与写锁之间互斥。

注意:MDL锁是表锁,会对整张表加锁。

普及额外的小知识点,什么是DML和DDL:

DML(Data Manipulation Language)数据操纵语言:

适用范围:对表数据进行操作,比如 insert、delete、select、update等。

DDL(Data Definition Language)数据定义语言:

适用范围:对表结构进行操作,比如create、drop、alter、rename、truncate等。

3. 如何优雅的给线上表加字段

既然修改表结构的时候,MySQL会自动添加表锁,并且是写锁,会阻塞后续的所有读写请求,造成非常严重的后果。

还有没有办法能优雅的给线上表添加字段呢?

当然有,从MySQL5.6版本开始增加了Online DDL,作用就是在执行DDL的时候,允许并发执行DML。简单翻译就是修改表结构的时候,也能同时支持并发执行增删查改操作。

从MySQL8.0版本开始又优化了Online DDL,支持快速添加列,可以实现给大表秒级加字段。

具体用法就是在DDL语句后面增加两个参数ALGORITHMLOCK

比如下面这样:

  1. ALTER TABLE `user` ADD `age` int NOT NULL DEFAULT '0' COMMENT '年龄',
  2. ALGORITHM=Inplace,
  3. LOCK=NONE;

这两个参数分别是干嘛用的?有哪些选项呢?

ALGORITHM可以指定使用哪种算法执行DDL,可选项有:

  • Copy:

    拷贝方式,MySQL5.6 之前 DDL 的执行方式,过程就是先创建新表,修改新表结构,把旧表数据复制到新表,删除旧表,重命名新表。执行过程非常耗时,产生大量的磁盘IO和占用CPU,还有使Buffer poll失效,而且需要锁住旧表,性能较差,现在基本很少使用。

  • Inplace:

    原地修改,MySQL5.6开始引入的,优点是不会在Server层发生表数据拷贝,过程中允许并发执行DML操作。过程就是先添加MDL写锁,执行初始化操作,然后降级为MDL读锁,执行DDL操作(比较耗时,允许并发执行DML操作),升级为MDL写锁,完成DDL操作。

  • Instant:

    快速修改,MySQL8.0开始引入的,可以实现快速给大表添加字段。

性能依次是,Instant > Inplace > Copy。

LOCK可以指定执行过程中,是否加锁,可选项有:

  • NONE

    不加锁,允许DML操作。

  • SHARED

    加读锁,允许读操作,禁止DML操作。

  • DEFAULT

    默认锁模式,在满足DDL操作前提下,默认锁模式会允许尽可能多的读操作和DML操作。

  • EXCLUSIVE

    加写锁,禁止读操作和DML操作。

Online DDL并不是支持所有DDL操作,看一下到底支持哪些操作?

操作 Instant Inplace Rebuilds Table 允许并发DML 仅修改元数据
添加列 Yes Yes No Yes No
删除列 No Yes Yes Yes No
重命名列 No Yes No Yes Yes
更改列顺序 No Yes Yes Yes No
设置列默认值 Yes Yes No Yes Yes
更改列数据类型 No No Yes No No
设置VARCHAR列大小 No Yes No Yes Yes
删除列默认值 Yes Yes No Yes Yes
更改自动增量值 No Yes No Yes No
设置列为null No Yes Yes Yes No
设置列not null No Yes Yes Yes No

像最常见的添加列就可以使用Instant,而像删除列、重命名列、更改列数据类型就只能使用Inplace了。

线上服务宕机,码农试用期被毕业,原因竟是给MySQL加个字段的更多相关文章

  1. 最近两周我们接触到的两种线上抓娃娃机的技术实现方案(一种RTSP/一种RTMP)

    线上抓娃娃机需求 最近线上抓娃娃机的项目火爆了,陆陆续续几十款线上抓娃娃机上架,还有一大波正在开发上线中,各大视频云提供商都在蹭热度发布自己的线上抓娃娃机方案,综合了一下,目前线上抓娃娃机的视频需求无 ...

  2. 记-ItextPDF+freemaker 生成PDF文件---导致服务宕机

    摘要:已经上线的项目,出现服务挂掉的情况. 介绍:该服务是专门做打印的,业务需求是生成PDF文件进行页面预览,主要是使用ItextPDF+freemaker技术生成一系列PDF文件,其中生成流程有:解 ...

  3. 线上服务的FGC问题排查,看这篇就够了!

    线上服务的GC问题,是Java程序非常典型的一类问题,非常考验工程师排查问题的能力.同时,几乎是面试必考题,但是能真正答好此题的人并不多,要么原理没吃透,要么缺乏实战经验. 过去半年时间里,我们的广告 ...

  4. 记一次线上服务CPU 100%的处理过程

    告警 正在开会,突然钉钉告警声响个不停,同时市场人员反馈客户在投诉系统登不进了,报504错误.查看钉钉上的告警信息,几台业务服务器节点全部报CPU超过告警阈值,达100%. 赶紧从会上下来,SSH登录 ...

  5. 糟了,线上服务出现OOM了

    前言 前一段时间,公司同事的一个线上服务OOM的问题,我觉得挺有意思的,在这里跟大家一起分享一下. 我当时其实也参与了一部分问题的定位. 1 案发现场 他们有个mq消费者服务,在某一天下午,出现OOM ...

  6. Linux(2)---记录一次线上服务 CPU 100%的排查过程

    Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过 ...

  7. 由Redis的hGetAll函数所引发的一次服务宕机事件

    昨晚通宵生产压测,终于算是将生产服务宕机的原因定位到了,心累.这篇博客,算作一个复盘和记录吧... 先来看看Redis的缓存淘汰算法思维导图: 说明:当实际占用的内存超过Redis配置的maxmemo ...

  8. 线上服务CPU100%问题快速定位实战

    功能问题,通过日志,单步调试相对比较好定位. 性能问题,例如线上服务器CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底. 58到家架构部,运维部,58速运技术部联合进行了一次线上 ...

  9. 线上服务内存OOM问题定位[转自58沈剑]

    相信大家都有感触,线上服务内存OOM的问题,是最难定位的问题,不过归根结底,最常见的原因: 本身资源不够 申请的太多 资源耗尽 58到家架构部,运维部,58速运技术部联合进行了一次线上服务内存OOM问 ...

随机推荐

  1. 乘风破浪,遇见未来新能源汽车(Electric Vehicle)之特斯拉提车必须知道的十个流程

    订车 线下门店或者官网可以咨询和下单,一般来说,订金就是1000,还算可以接受. 订单账号 特斯拉账号是以邮箱为区分的,而不是手机号,我们下单的时候需要提供一个邮箱用来注册特斯拉账号. 注意了,敲黑板 ...

  2. 关于奇妙的 Fibonacci 的一些说明

    奇妙的 Fibonacci,多次模拟赛中出现 同时也是 BZOJ 2813 一 Fibonacci 的 GCD 如果 \(F\) 是 Fibonacci 数列,那么众所周知的有 \(\gcd(F_i, ...

  3. Fibonacci Nim

    目录 题意 题解 相关 Ref 题意 [COCI2010-2011#4] HRPA 取石子,但是: 先手第一次可取任意多个石子 此外每次可取的石子的个数,至少为 \(1\) ,至多为上一轮对方所取个数 ...

  4. Linux上安装java

    1,输入命令,查看是否已经安装了Openjdk:rpm -qa | grep java 如果有已经安装的java版本或者版本低于1.7,卸载该jdk:rpm -e 软件包名字 如果不能卸载,可以加上 ...

  5. C#任务并行库TPL--Task应用

    一.概念 TPL的核心就是任务,一个任务代表一个异步操作,该操作可以通过多种方式运行,一个任务也可以由多个任务组成. 二.应用 1.创建任务有三种方法: var t1 = new Task(() =& ...

  6. Java多线程开发系列之五:Springboot 中异步请求方法的使用

    Springboot 中异步线程的使用在过往的后台开发中,我们往往使用java自带的线程或线程池,来进行异步的调用.这对于效果来说没什么,甚至可以让开发人员对底层的状况更清晰,但是对于代码的易读性和可 ...

  7. postgresql使用group by进行数据去重-2022新项目

    一.业务场景 数据去重是web开发中经常会遇到的方式之一,数据库操作中有一个关键字distinct主要就是用来做这件事,用来进行去重. 比如进行统计查询的时候,可以这样写 select count(d ...

  8. iommu分析之---DMA remap框架实现

    本文主要介绍iommu的框架.基于4.19.204内核 IOMMU核心框架是管理IOMMU设备的一个通过框架,IOMMU设备通过实现特定的回调函数并将自身注册到IOMMU核心框架中,以此通过IOMMU ...

  9. NOI2021 同步赛游记

    写在前面的话 为什么叫游记呢?因为我第一天是在划水中度过的,错过了对原题的发现. O n e I n D a r k \tt OneInDark OneInDark 无比风光地去了浙江,却倒霉地遇上了 ...

  10. P7727 风暴之眼 Eye of the Storm (树形 DP)

    谨 以 此 文 表 达 笔 者 个 人 观 点 , 如 有 冒 犯 官 解 , 可 在 评 论 区 诉 说 _{^{_{谨以此文表达笔者个人观点,如有冒犯官解,可在评论区诉说}}} 谨以此文表达笔者个 ...