热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

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

试想一下这个场景

事务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-ostpt-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的安装、使用,使用还是非常简单的,参数也只给大家说明了常用的,如果要放到生产环境使用,你需要把所有的参数都简单过一遍。

最后用一个脚本优化了修改表信息时需要输入的一大堆重复信息。


坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮助,我是咔咔,下期见。




推荐阅读
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
author-avatar
神話南帝冫
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有