闯祸了,生成环境执行了DDL操作《死磕MySQL系列 十四》
由于业务随着时间不停的改变,起初的表结构设计已经满足不了如今的需求,这时你是不是想那就加字段呗!加字段也是个艺术活,接下来由本文的主人咔咔给你吹。
试想一下这个场景
事务A在执行一个非常大的查询
事务B毫不犹豫的执行了DDL操作
接下来会发生什么,你如果已经知道答案的话恭喜你又掌握了一个MySQL中重要的知识点。
事务A执行查询时会持有MDL锁,而事务B同样也需要MDL锁,但事务A在进行大查询,所以导致事务B后的所有操作都会被堵塞。
这时你应该知道了在MySQL中所有对表的增删改查都需要申请MDL读锁。
接下来聊聊如何安全的给表加个字段
最新文章
MySQL统计总数就用count(*),别花里胡哨的《死磕MySQL系列 十》
为什么MySQL字符串不加引号索引失效?《死磕MySQL系列 十一》
打开order by的大门,一探究竟《死磕MySQL系列 十二》
一、为什么不建议你在生产环境下进行DDL
上期文章跟大家聊过的MDL锁的知识还记得吧!不记得也没事,那就在这篇文章中再进行复习。
MDL锁不需要显示调用,当对一个表做增删改查时会默认加MDL读锁,而执行修改表结构时会默认加MDL写锁。
这也就是文章开头给大家说的事务B是不能在事务A没释放MDL读锁之前执行。
事务B需要的是MDL写锁,MDL读锁与写锁是互斥关系,因此事务B的DDL操作会一直等待事务A提交并释放MDL锁
但你有没有想过一个问题,此时的事务B执行的在线DDL操作,需要的是MDL写锁,上文也说了对一个表做增删改查时会默认加MDL读锁,这不就意味着后续对这个表的所有操作都会堵塞吗?
所以说坚决不要在生产环境进行在线DDL,现在的客户端都有会重试机制,当堵塞的语句超时后会再起一个新的事务在请求,这张表假设是一个热表,MySQL库的线程会非常快就爆满,等待的结果就是用户那边迟迟响应不了结果。
这里给大家一个方案,当你十分紧急需要添加一个字段时,可以给语句设置一个时间,如果在这个设定的时间内能拿到MDL写锁最好,拿不到也会阻塞后续的业务语句。
当设置的这个时间超过后,这个指令就结束了,之后可以再次重复执行这个指令即可。
执行语法为alter table table_nam wait 10 add cloumn
这个方案也是在你的表不大的情况下才可以进行执行的,假设你的表就看第二种方案哈!要不你会死的很惨。
咔咔在一张近9000W数据的开发表上做过一次DDL操作,大概用了23s这样一个时间,这要是在线上想想都害怕
二、如何安全给表加个字段
目前咔咔知道的第三方工具有gh-ost
和pt-online-schema-change
,咔咔所在的公司使用的是后者,对于这两个插件后者的使用还是多点。
还记得在前几期文章中提到了表数据都删完了,但表空间依然没有缩小,在那期就简单的提了一下。
想要缩小表空间可以新建一模一样的表结构,然后根据主键ID的顺序把数据从就旧表中逐行插入新表,这样就可以减少表空洞的问题。
同理今天要说的pt-online-schema-change
这个插件的工作流程大致如下
- 新建一模一样的表,表名可以起为_new后缀
- 接着在这个新表执行更改字段操作
- 接着在原表上加三个触发器,分别为delete、update、insert,将原表中要执行的语句也在新表中执行
- 最后将原表的数据拷贝到新表中,替换掉原表
接下来咔咔将亲自实战一下此操作,可以跟着咔咔的步骤一起来
三、使用pt-online-schema-change
安装步骤
yum -y install perl perl-DBI perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL perl-Digest-MD5
wget https://www.percona.com/downloads/percona-toolkit/3.1.0/binary/redhat/7/x86_64/percona-toolkit-3.1.0-2.el7.x86_64.rpm
rpm -ivh percona-toolkit-3.1.0-2.el7.x86_64.rpm
rm -f percona-toolkit-3.1.0-2.el7.x86_64.rpm
安装完成后执行./bin/pt-online-schema-change --help
,出现以下界面证明你就安装成功了
参数认识
参数是非常多的,咔咔简单的说几个足够修改表结构的
- --user 连接mysql用户名
- --password 连接mysql密码
- --host 连接msyql地址
- p 连接mysql端口号
- D 连接mysql库名
- t 连接msyql表名
- --alter 修改表结构的语句
- --execute 执行修改表结构
- --charset=utf8 使用utf8编码,避免中文乱码
- --no-version-check 不检查版本,在阿里云服务器中一般加入此参数,否则会报错
接下来使用pt-online-schema-change
修改一下表结构
这个是目前默认的数据结构,现在想要添加邮箱字段
在这块你大概率会遇到两个错误,一个是你的密码中标点符号,另一个是pt版本问题
处理完密码中的标点符号就会来到下面这个错误
执行代码./bin/pt-online-schema-change --charset=utf8 --no-version-check --user="root" --password="Fang1996" --host="127.0.0.1" D="kaka",t=evt_sms --alter "add column email varchar(255) not null default '' after phone" --print --execute
这个问题是pt-online-schema-change
版本造成的
删除之前的版本
yum remove percona-toolkit
重新安装新版本的rpm包即可,安装步骤如下
wget https://downloads.percona.com/downloads/percona-toolkit/3.2.0/binary/redhat/7/x86_64/percona-toolkit-3.2.0-1.el7.x86_64.rpm
rpm -ivh percona-toolkit-3.2.0-1.el7.x86_64.rpm
这一步部分小伙伴会遇到其它资料给的地址太过老旧,导致一直下载不了,咔咔提供的这个地址是官网提取的,非常好用,https://www.percona.com/downloads/percona-toolkit/3.2.0/binary/redhat/7/
这里可以获取各个版本的rpm包
咔咔亲测虚拟机的下载速度要不服务器快,于是先将文件下载到了虚拟机
然后使用scp直接把虚拟机的文件传输到主机上,执行命令为 scp percona-toolkit-3.2.0-1.el7.x86_64.rpm root@ip:/
使用语法非常简单scp local_file remote_username@remote_ip:remote_folder
local_file :本地文件
remote_username:远程用户名
remote_ip:远程机器IP地址
remote_folder 远程目录
执行完成后需要输入服务器密码,然后等待传输完成就可以在服务器上看到对应的文件
这里分别在虚拟机、服务器查看了文件大小,文件是没有一点问题的
到这里对于pt-online-schema-change的安装才完成,接下来重试之前执行的命令
./bin/pt-online-schema-change --charset=utf8 --no-version-check --user="root" --password="Fang1996" --host="127.0.0.1" D="kaka",t=evt_sms --alter "add column email varchar(255) not null default '' after phone" --print --execute
以上就是修改成功的信息,可以看到处理数据有46W,基本是毫无压力,建议大家实测一下
可以看到要加的email字段已经加上了,这个就是我们想要的结果
四、简化pt-online-schema-change的执行命令
在执行修改表结构命令时输入了很多配置信息, 这些信息可以放在脚本里边复用的
#!/bin/bash
database=$1
table=$2
alter_conment=$3
pt_host='127.0.0.1'
pt_user='root'
pt_pwd='Fang1996'
echo "$table"
echo "$alter_conment"
/bin/pt-online-schema-change --charset=utf8 --no-version-check --user=${pt_user} --password=${pt_pwd} --host=${pt_host} P=3306,D=$database,t=$table --alter "${alter_conment}" --print --execute
那么使用pt-online-schema-change则可以这样写
sh pt.sh kaka evt_sms "add column kaka1 varchar(255) default '咔咔'"
这里给大家提供了添加字段的方法,修改、删除都是一致的,只需要把对应的语句放到引号
里边即可
在这里你会发现只有进到脚本的目录才能执行对应的脚本,那么如何让你的脚本可以在任意地方都可以执行呢?
五、总结
本期文章给大家详细说明了为什么不建议大家直接在线DDL,因为会阻塞SQL导致业务停摆
给大家介绍了第三方脚本pt-online-schema-change的安装、使用,使用还是非常简单的,参数也只给大家说明了常用的,如果要放到生产环境使用,你需要把所有的参数都简单过一遍。
最后用一个脚本优化了修改表信息时需要输入的一大堆重复信息。
坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮助,我是咔咔,下期见。
闯祸了,生成环境执行了DDL操作《死磕MySQL系列 十四》的更多相关文章
- 原来一条select语句在MySQL是这样执行的《死磕MySQL系列 一》
前言 看到蒋老师的第一篇文章后就收货颇丰,真是句句戳中痛点. 令我记忆最深的就是为什么知道了一个个技术点,却还是用不好 ?不管是蒋老师所说的Redis还是本系列要展开学习的MySQL. 这是一个值得思 ...
- MySQL 系列(四)主从复制、备份恢复方案生产环境实战
第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...
- katalon系列十四:执行Windows命令&获取项目路径
Katalon Studio中也可以运行Windows命令执行一些系统操作. 根据官方文档,在test case中输入命令:cmd = 'del E:\\shot\\*.xlsx E:\\shot\\ ...
- MySQL 系列(四) 主从复制、读写分离、模拟宕机、备份恢复方案生产环境实战
本章内容: 主从复制 简介原理 备份主库及恢复从库,配置从库生效 读写分离 如果主宕机了,怎么办? 双主的情况 MySQL 备份及恢复方案 备份单个及多个数据库 mysqldump 的常用参数 如何增 ...
- Java中执行存储过程和函数(web基础学习笔记十四)
一.概述 如果想要执行存储过程,我们应该使用 CallableStatement 接口. CallableStatement 接口继承自PreparedStatement 接口.所以CallableS ...
- Replication的犄角旮旯(六)-- 一个DDL引发的血案(上)(如何近似估算DDL操作进度)
<Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...
- 【科普】MySQL中DDL操作背后的并发原理
一. 简介 DQL:指数据库中的查询(select)操作. DML:指数据库中的插入(insert).更新(update).删除(delete)等行数据变更操作. DDL:指数据库中加列(add co ...
- mysql系列九、mysql语句执行过程及运行原理(分组查询和关联查询原理)
一.背景介绍 了解一个sql语句的执行过程,了解一部分都做了什么,更有利于对sql进行优化,因为你知道它的每一个连接.where.分组.子查询是怎么运行的,都干了什么,才会知道怎么写是不合理的. 大致 ...
- MySQL--各版本DDL 操作总结
MySQL 5.5 DDL 在MySQL 5.5版本前,所有DDL操作都使用Copy Table的方式完成,操作过程中原表数据库不允许写入,只能读取,在MySQL 5.5版本中引入FIC(Fast i ...
随机推荐
- STL 较详尽总结
STL就是Standard Template Library,标准模板库.这可能是一个历史上最令人兴奋的工具的最无聊的术语.从根本上说,STL是一些"容器"的集合,这些" ...
- 【密码学】AES简单学习
欧拉函数 公式 φ(n)=(p-1)(q-1) 小于x并且和x互质的数的个数 相关概念 因数:a*b=c 那么就称 a.b 是 c 的因数 素数:一个数如果除了1与它本身之外没有其他的因数,那么 ...
- 【密码学】CBC反转字节攻击
前言 暑假刷安全牛的课,看视频有点够了,想做点题,选择了实验吧,结果上来就整懵了 web题,牵扯到了CBC反转字节攻击,密码学!? 查阅资料,学习一下 CBC加解密 CBC 模式中会先将明文分组与前一 ...
- LuoguP7870 「Wdoi-4」兔已着陆 题解
Content 对一个栈执行如下操作: 1 l r:依次向栈里面弹入 \(l,l+1,\dots,r-1,r\). 2 k:依次从栈里面弹出 \(k\) 个数,并求出所有弹出的数的和. 数据范围:\( ...
- CF1547A Shortest Path with Obstacle 题解
Content 给定两个在二维平面上的网格 \(A(x_A,y_A)\) 和 \(B(x_B,y_B)\),另外,还有一个不可通过的网格 \(F(x_F,y_F)\).你需要求出在不经过 \(F\) ...
- SpringCloud Alibaba实战(12:引入Dubbo实现RPC调用)
源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 大家好,我是老三,断更了半年,我又滚回来继续写这个系列了,还有人看吗-- 在前面的章 ...
- ConfigParser模块,主要应用于对php.ini等格式的配置文件内容读取和生成。删改较少用
*.ini配置文件样例 创建默认的文件样例 读取文件内容 read() configparser增删改查语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...
- 深入理解css中position属性及z-index属性 https://www.cnblogs.com/zhuzhenwei918/p/6112034.html
深入理解css中position属性及z-index属性 请看出处:https://www.cnblogs.com/zhuzhenwei918/p/6112034.html 在网页设计中,positi ...
- 七种可能 | Linux丢包故障的定位与解决
出处[云英公众号]:https://mp.weixin.qq.com/s?__biz=MzI1NzM3NTYxMw==&mid=2247483685&idx=1&sn=95c8 ...
- 【LeetCode】1120. Maximum Average Subtree 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 日期 题目地址:https://leetcod ...