MySQL之使用pt-online-schema-change在线修改大表结构
原因: 最近公司上一个功能, 需要为其中某个表中新增字段,但是考虑到线上数据已经达到300w+的级别,同时使用的mysql的版本是5.7而非8.0,这会导致新增字段的时候,对全表进行加锁,直到添加完毕这个过程中可能会消耗至少几十秒钟的时间,极大的影响线上业务
解决方案:
1.升级MySQL版本到8.0版本,支持行级锁
2.使用pt-online-schema-change工具
这里使用pt-online-schema-change, 由于MySQL的升级会导致不稳定的情况
大表执行DDL可能导致的问题:
在线修改大表的表结构执行时间往往不可预估,一般时间较长
由于修改表结构是表级锁,因此在修改表结构时,影响表写入操作
如果长时间的修改表结构,中途修改失败,由于修改表结构是一个事务,因此失败后会还原表结构,在这个过程中表都是锁着不可写入
修改大表结构容易导致数据库CPU、IO等性能消耗,使MySQL服务器性能降低
在线修改大表结构容易导致主从延时,从而影响业务读取
[介绍]
pt-online-schema-change是percona公司开发的一个工具,在percona-toolkit包里面可以找到这个功能,它可以在线修改表结构
原理
1.创建一个和要执行 alter 操作的表一样的新的空表结构(是alter之前的结构)
2.在新表执行alter table 语句(速度应该很快)
3.在原表中创建触发器3个触发器分别对应insert,update,delete操作
4.以一定块大小从原表拷贝数据到临时表,拷贝过程中通过原表上的触发器在原表进行的写操作都会更新到新建的临时表
5.Rename 原表到old表中,在把临时表Rename为原表
6.如果有参考该表的外键,根据alter-foreign-keys-method参数的值,检测外键相关的表,做相应设置的处理
7. 默认最后将旧原表删除
如果执行失败了,或手动停止了,需要手动删除下划线开头的表(_表名)及三个触发器
[安装]
ubuntu)
1.下载percona存储库文件
sudo apt update sudo apt -y install gnupg2 wget wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
2.安装percona存储库包
sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
输出如下:
Selecting previously unselected package percona-release. (Reading database ... 194365 files and directories currently installed.) Preparing to unpack percona-release_latest.focal_all.deb ... Unpacking percona-release (1.0-17.generic) ... Setting up percona-release (1.0-17.generic) ... * Enabling the Percona Original repository <*> All done! ==> Please run "apt-get update" to apply changes The percona-release package now contains a percona-release script that can enable additional repositories for our newer products. For example, to enable the Percona Server 8.0 repository use: percona-release setup ps80 Note: To avoid conflicts with older product versions, the percona-release setup command Jan disable our original repository for some products. For more information, please visit: https://www.percona.com/doc/percona-repo-config/percona-release.html
3.安装Percona Toolkit
sudo apt update
sudo apt install percona-toolkit
同意软件安装:
Reading package lists... Done Building dependency tree Reading state information... Done The following packages were automatically installed and are no longer required: geoip-database gsfonts libapt-pkg5.90 libbind9-161 libcroco3 libdns-export1107 libdns1107 libdns1109 libgeoip1 libicu65 libirs161 libisc-export1104 libisc1104 libisc1105 libisccc161 libisccfg163 liblwres161 libmozjs-60-0 liboauth0 libpoppler95 linux-modules-extra-5.4.0-14-generic ubuntu-system-service Use 'sudo apt autoremove' to remove them. The following additional packages will be installed: libdbd-mysql-perl libdbi-perl libterm-readkey-perl Suggested packages: libclone-perl libmldbm-perl libnet-daemon-perl libsql-statement-perl The following NEW packages will be installed: libdbd-mysql-perl libdbi-perl libterm-readkey-perl percona-toolkit 0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded. Need to get 1,732 kB of archives. After this operation, 10.3 MB of additional disk space will be used. Do you want to continue? [Y/n] y
[使用]
1.查看MySQL性能摘要
pt-mysql-summary --host localhost --user root --ask-pass
2.修改表结构
pt-online-schema-change --alter "add column t8 int(11) not null default 0" D=test,t=log,h=192.168.16.48,P=3306,u=root,p=123456 --print --execute --charset=utf8
注意:
--charset=utf8
,有的时候修改后的表注释出现乱码,或者如下报错,就必须要加上这个参数
参数 说明
–user/u 连接mysql的用户名
–password/p 连接mysql的密码
–host/h 连接mysql的地址
P=3306 连接mysql的端口号
D= 连接mysql的库名
t= 连接mysql的表名
–alter 修改表结构的语句
–execute 执行修改表结构
–charset=uft8 使用utf8编码,避免中文乱码
–no-version-check 不检查版本,在阿里云服务器中一般加入此参数,否则会报错
--user: -u,连接的用户名 --password: -p,连接的密码 --database: -D,连接的数据库 --port -P,连接数据库的端口 --host: -h,连接的主机地址 --socket: -S,连接mysql套接字文件 --statistics 打印出内部事件的数目,可以看到复制数据插入的数目。 --dry-run 创建和修改新表,但不会创建触发器、复制数据、和替换原表。并不真正执行,可以看到生成的执行语句,了解其执行步骤与细节。--dry-run与--execute必须指定一个,二者相互排斥。和--print配合最佳。 --execute 确定修改表,则指定该参数。真正执行。--dry-run与--execute必须指定一个,二者相互排斥。 --print 打印SQL语句到标准输出。指定此选项可以让你看到该工具所执行的语句,和--dry-run配合最佳。 --progress 复制数据的时候打印进度报告,二部分组成:第一部分是百分比,第二部分是时间。 --quiet -q,不把信息标准输出。
性能分析:
4.1 使用存储过程
首先使用存储过程做测试,为防止锁表,每次只更新200行。整个变更从开始到完成,需要耗费90分钟。其实,存储过程在执行过程中,如果恰好用户也在DDL操作存储过程正在变更的数据行,还有可能会锁住用户的数据,导致用户不能变更成功。
4.2 使用pt-osc工具
pt-osc从开始执行到变更完成,耗时7分钟左右,速度非常快。在执行的过程中,测试环境的服务连接到该数据库,并执行多个会操作该表的任务,整个过程中,任务能够正常执行,未出现异常情况。
- 500万的数据,新增一个int字段,花费大概30s时间
参考:
https://www.cnblogs.com/keme/p/10237590.html#auto_id_0
https://juejin.cn/post/6918908595778093070