闯祸了,生产环境执行了DDL操作《死磕MySQL系列 十四》(1)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 闯祸了,生产环境执行了DDL操作《死磕MySQL系列 十四》

由于业务随着时间不停的改变,起初的表结构设计已经满足不了如今的需求,这时你是不是想那就加字段呗!加字段也是个艺术活,接下来由本文的主人咔咔给你吹。


试想一下这个场景


事务A在执行一个非常大的查询


事务B毫不犹豫的执行了DDL操作


接下来会发生什么,你如果已经知道答案的话恭喜你又掌握了一个MySQL中重要的知识点。


事务A执行查询时会持有MDL锁,而事务B同样也需要MDL锁,但事务A在进行大查询,所以导致事务B后的所有操作都会被堵塞。


这时你应该知道了在MySQL中所有对表的增删改查都需要申请MDL读锁。


接下来聊聊如何安全的给表加个字段




最新文章

死磕MySQL系列总目录


MySQL统计总数就用count(*),别花里胡哨的《死磕MySQL系列 十》


为什么MySQL字符串不加引号索引失效?《死磕MySQL系列 十一》


打开order by的大门,一探究竟《死磕MySQL系列 十二》


重重封锁,让你一条数据都拿不到《死磕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,出现以下界面证明你就安装成功了


image.png


参数认识


参数是非常多的,咔咔简单的说几个足够修改表结构的


  • –user 连接mysql用户名
  • –password 连接mysql密码
  • –host 连接msyql地址
  • p 连接mysql端口号
  • D 连接mysql库名
  • t 连接msyql表名
  • –alter 修改表结构的语句
  • –execute 执行修改表结构
  • –charset=utf8 使用utf8编码,避免中文乱码
  • –no-version-check 不检查版本,在阿里云服务器中一般加入此参数,否则会报错


接下来使用pt-online-schema-change修改一下表结构


这个是目前默认的数据结构,现在想要添加邮箱字段


image.png


在这块你大概率会遇到两个错误,一个是你的密码中标点符号,另一个是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


image.png


这个问题是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包


咔咔亲测虚拟机的下载速度要不服务器快,于是先将文件下载到了虚拟机


image.png



相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
关系型数据库 MySQL 数据安全/隐私保护
MySQL8.0生产环境二进制标准安装
MySQL8.0生产环境二进制标准安装
|
4月前
|
SQL 运维 关系型数据库
MySQL 中 GRANT 操作会引起复制中断吗?
GRANT 操作并不是一个原子性操作,不管执行成功与否,都会触发一个隐式重载授权表的行为。 在生产环境中需要规范用户创建及授权的操作,不推荐使用 DML 语句去直接变更 mysql.user 表,可能会引发其他的问题,若使用了 DML 语句进行变更, 需要手工执行 flush privileges。
68 4
|
4月前
|
JavaScript 关系型数据库 MySQL
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
64 0
|
16天前
|
SQL 关系型数据库 MySQL
|
1月前
|
SQL 关系型数据库 MySQL
MySQL 更新1000万条数据和DDL执行时间分析
MySQL 更新1000万条数据和DDL执行时间分析
98 4
|
3月前
|
关系型数据库 MySQL 数据安全/隐私保护
MySQL5.7生产环境二进制标准安装
MySQL5.7生产环境二进制标准安装
|
3月前
|
SQL 存储 关系型数据库
"MySQL增列必锁表?揭秘InnoDB在线DDL,让你的数据库操作飞一般,性能无忧!"
【8月更文挑战第11天】在数据库领域,MySQL凭借其稳定高效的表现深受开发者喜爱。对于是否会在给数据表添加列时锁表的问题,MySQL的行为受版本、存储引擎等因素影响。从5.6版起,InnoDB支持在线DDL,可在改动表结构时保持表的可访问性,避免长时间锁表。而MyISAM等则需锁表完成操作。例如,在使用InnoDB的表上运行`ALTER TABLE users ADD COLUMN email VARCHAR(255);`时,通常不会完全锁表。虽然在线DDL提高了灵活性,但复杂操作或大表变更仍可能暂时影响性能。因此,进行结构变更前应评估其影响并择机执行。
71 6
|
4月前
|
SQL 算法 关系型数据库
Mysql Online DDL
Mysql Online DDL
44 2
|
4月前
|
存储 关系型数据库 文件存储
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
47 2
|
4月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错合集之从mysql读数据写到hive报错,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。