pt-online-schema-change的原理解析与应用说明
1 原理介绍
- ALTER操作期间,表格是否支持DML?
- 如果支持DML,是如何把DML同步到新的临时表上?
- 整个操作流程锁情况是怎么样的?
- 执行期间有什么性能影响?
- 该工具有什么限制情况?
1.1 详细执行流程
- 相关环境参数检查
- 检查该表格是否存在
- show create table tbosc
- create table _tbosc_new
- alter table _tbosc_new
- 创建删除触发器 pt_osc_dbddl_tbosc_del (如果数据修改的时候,还没有拷贝过来,修改后再拷贝则是覆盖,正确;如果是已经拷贝过来,再修改,也是正确,这里同时会检查是否具有主键或者唯一索引,如果都没有,这一步会报错,提示The new table `dbosc`.`_tbosc_new` does not have a PRIMARY KEY or a unique index which is required for the DELETE trigger.)
- 创建更新触发器 pt_osc_dbddl_tbosc_upd
- 创建插入触发器 pt_osc_dbddl_tbosc_ins
- 按块拷贝数据到新表,拷贝过程对数据行持有S锁
- analyze 新表
- rename 表名,RENAME TABLE `dbddl`.`tbosc` TO `dbddl`.`_tbosc_old`, `dbddl`.`_tbosc_new` TO `dbddl`.`tbosc`
- 删除旧表
- 删除新表上的删除、更新、插入 触发器
1.2 问题解答
- ALTER操作期间,表格是否支持DML?
- ALTER过程采用Copy Table To New Table的方式,新建一个表格,然后在原表上创建3个触发器:DELETE\UPDATE\INSERT触发器,一旦新表,拷贝数据到新表的过程中,如果原表数据发生变化,则会通过触发器更新到新表上。
- 如果支持DML,是如何把DML同步到新的临时表上?
- ALTER过程采用Copy Table To New Table的方式,新建一个表格,然后在原表上创建3个触发器:DELETE\UPDATE\INSERT触发器,一旦新表,拷贝数据到新表的过程中,如果原表数据发生变化,则会通过触发器更新到新表上。
- INSERT原表的时候,触发器根据其主键ID把新纪录INSERT到新表上;
- UPDATE原表的时候,触发器根据其主键ID判断新旧ID是否一致,如果一致则删除,然后在REPLACE INTO新纪录到新表
- DELETE原表的时候,触发器根据其主键ID直接删除行记录
- 如果数据修改的时候,还没有拷贝到新表,修改后再拷贝,虽然重复覆盖,但是数据也没有出错;如果是数据已经拷贝,原表发生修改,这时触发器同步修改数据,两种情况下都保证了数据的一致性;
- 整个操作流程锁情况是怎么样的?
- 创建新表后,按照每一个chunk的大小拷贝数据到新表,每次SELECT都是share mode,带S锁,但是每个chunk都比较小,所以锁时间不大
- 最后数据拷贝结束,会有一个rename操作,这个操作过程中,是不支持DML操作的,但其速度很快,不会造成长时间锁表情况
- 该工具会设置该DDL操作的锁等待超时为1s,当出现异常的时候,会是ALTER操作异常,而不是其他业务操作异常,这样可以最大程度的不影响其他事务的进行
- 执行期间有什么性能影响?
- 总体而言,对数据库的锁影响降低到了最小,执行期间允许DML操作
- 但是注意,任何DDL SQL在这里,都是转换成copy table to new table的形式,这个过程中,会极大占用磁盘的IO跟CPU资源,同时跟住从延时带来一定的影响,还是那句老话,重复了解DDL的影响程度后,再选择合适时机执行。
- copy data过程中,如果主从延迟异常超过 max-lag则停止copy data,等待主从延迟恢复,默认为1min,可以通过--max-lag设置
- 检测到服务器负载异常,也会停止操作,可以通过 --max-load,--critical-load设置
- 该工具有什么限制情况?
- 表格必须带有主键或者唯一索引
- 存在复制过滤掉表格,ALTER操作
- copy data过程中,如果主从延迟异常超过 max-lag则停止copy data,等待主从延迟恢复,默认为1s,可以通过--max-lag设置
- 检测到服务器负载异常,也会停止操作,可以通过 --max-load,--critical-load设置
- 设置操作的锁等待超时为1s,当出现异常的时候,ALTER操作异常,而不是其他业务操作异常,这样可以最大程度的不影响其他事务的进行
- 默认情况下,存在 被外键引用的表格是不支持ALTER操作的,除非手动指定参数--alter-foreign-keys-method
- 不支持修改 Percona XtraDB Cluster (PXC)上节点的 myisam表格
2 环境准备
3 语法说明
3.1 主要选项
- --alter
- 指定ALTER 语句,正常的ALTER TABLE TBNAME [ ADD | MODIFY | DROP | ALTER ] COLUMN COLUMN_NAME ...,去除前面的ALTER TABLE TABLE那么,直接指定后部分的内容
- 注意事项
- rename不支持,请直接使用RENAME TABLE tablename TO new_tablename;
- 如果表格有数据,创建非空无默认值的列,会失败,如果非空,需要指定默认值;
- 如果表格有数据,为一个可空的列添加默认值时,旧数据为NULL的是不会被修改,依旧为NULL,以后新加入到数据则会默认为设置的默认值
- 对于外键的删除情况,由于执行是在新表上执行DDL,所以其外键值的命名跟原表的命名不一样,假设删除原表的外键名是 fk_foo,那么新表的外键名就为 _fk_foo,所以删除的ALTER语句是: drop foreign key _fk_foo;
- --alter-foreign-keys-method
- 如果修改的表格,是其他表格外键reference的表格,那么,最后rename的过程,需要确保一定成功,要不然这些子表就没能成功reference到其指定的表格名,对子表的操作将会报错。比如 tba有一个外键 fk_tba引用表格 tbb,这个时候tbb需要做DDL操作,根据pt工具的原理得知,最后会有一个rename环节,这个环节可能会导致约束失效或者执行堵塞等问题。
- 所以,针对最后rename的这个环节,该工具提供了4中处理方法:
- auto
- 自动选择 rebuild_constraints 或者 drop_swap,优先选择rebuild_constraints
- rebuild_constraints
- rename table 前,先删除子表的外键约束,然后重建外键约束指向到新表(ALTER TABLE语句添加),最后执行rename操作
- 这个rename操作即使不成功,它也rename到新表,不会出现reference的表格不存在情况
- 弊端:如果子表过大,添加外键约束的过程中,可能会对子表造成堵塞
- drop_swap
- 执行rename之前禁用外键检查,然后删除原表,rename新表为原表名
- 这个过程非常快并且没有堵塞
- 这个方法需要强制指定 --no-swap-tables 跟 --no-drop-old-table.
- 弊端:当把原表删除而新表还没rename为原表的名字时,这段时间实际非常短,但是这段时间内,等于原表名的表格时不存在的,子表做一些DML的时候,可能会出现错误。rename期间,如果新表rename原表失败,但是已经删除原表,那么这段期间,其子表的操作将会出现大面积问题,直到人工修复
- none
- 类似drop_swap操作,不同在于对原表的处理。
- 按正常的pt工具流程,禁用外键约束,rename原表为临时表,rename新表为原表名,删除临时表
- 弊端: 当把原表rename为临时表,而新表还没rename为原表的名字时,这段时间实际非常短,但是这段时间内,等于原表名的表格时不存在的,子表做一些DML的时候,可能会出现错误
- --drop-old-table
- 操作成功后,原表是否保留,默认是删除,
- default:yes,可选:--no-drop-old-table
- auto
- --dry-run
- 仅创建新表格,但是不执行触发器、拷贝数据跟替换原表
- --execute
- 确定执行ALTER操作,注意,这个操作如果不指定,则仅做安全检查然后推出。
- 充分了解工具的使用情况后,才执行,不要啥都不了解测试就线上执行,会挖坑的...
- --host
- 连接主机名
- --max-lag
- 默认1s
- 检查从库延迟的时间,如果超过,则停止copy data,休息--check-interval秒后,再重新开始copy数据
- 查看通过延迟时间,是通过从库show slave status,查看Seconds_Behind_Master
- 如果指定--check-slave-lag,该工具只检查该服务器的延迟,而不是所有服务器。
- --check-interval
- 从库延迟超过指定的--max-lag,中断copy data休息的时间
- 默认为1s
- --max-load
- copy data的过程,监控数据库当前正在运行的thread,如果超过指定的Threads_running值,则停止拷贝数据,会在输出的内容中答应 Pausing because Threads_runing=15,直到运行的线程数小于给定的值,恢复copy data,如此循环,知道拷贝数据结束。
- Threads_runing默认为25
- 举例:--max-load=Thread_running=15
- --password
- 数据库用户名的密码
- --port
- 数据库端口号
- --socket
- 数据库socket文件
- --user
- 数据库用户名
- --recursion-method
- MASTER寻找SLAVE的方式(这个选项基本在涉及主从问题的pt工具中广泛应用到)
- 有4个选项
- processlist,使用show processlist查找从库
- hosts,如果不是使用默认端口号3306,那么使用hosts方式来查找从库会更可靠
- dsn,使用表格 tdsn存储从库信息(DSN的具体参数选项可以详细查看 3.3 DSN选线)
- 需要手动在需要DDL的数据库内,创建 dsns 表格
- CREATE TABLE `dsns` (`id` int(11) NOT NULL AUTO_INCREMENT,`parent_id` int(11) DEFAULT NULL,`dsn` varchar(255) NOT NULL, PRIMARY KEY (`id`));
- 存储从库信息
- insert into dsns(dsn) values(h=slave_host,u=repl_user,p=repl_password,P=port );
- 该参数使用的时候,按以下格式(假设 dsns表格建立在数据库 dbosc)
- --recursion-method dsn=D=dbosc,t=dsns
- none,不查找从库
3.2 输出
- --statistics 增加影响行数打印,可以查看copy进度
- --print 详细打印alter过程,不指定的时候,简略打印
3.3 DSN选项
- A
- 字符集设置
- D
- 需要Alter的表格是在哪个数据库,指定数据库
- F
- mysql read default file,如果数据源的相关选项存储在文件中,则通过 F 来指定
- h
- host,数据库主机名或IP
- p
- password,数据库用户的密码
- P
- port,数据库实例端口号
- S
- socket,实例socket文件
- t
- 表格名
- u
- 用户名
4 使用举例
4.1 常规DDL
CREATE TABLE `tbosc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; #添加列
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "add column stunum int " --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #删除列
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "drop column stunum " --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #修改列数据类型
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "modify column age varchar(10)" --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #加大列长度
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "modify column age varchar(100)" --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #创建索引
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "ADD INDEX IX_AGE(AGE)" --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #删除索引
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "DROP INDEX IX_AGE" --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #设置默认值
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "ALTER column age SET DEFAULT 100" --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute #能否多个合成一个
pt-online-schema-change --socket=/tmp/mysql3310.sock --user=root --password=**** D=dbosc,t=tbosc --alter "ADD COLUMN onecol int ,add column twocol varchar(100),add index ix_onecol(onecol),alter column name set default 'xinysu' " --recursion-method=none --no-check-replication-filters --alter-foreign-keys-method auto --print --execute
4.2 考虑从库延迟情况
- --max-lag
- --check-interval
- --recursion-method
- --check-slave-lag
5 pt-osc还是online DDL?
- 如果MySQL版本是5.6之前,不支持online ddl操作的,pt-online-schema-change是一个非常好的选择;
- 如果MySQL的版本是5.6以上的,支持online-ddl的,优先考虑使用online ddl,但是如果是ddl SQL 在online DDL中 需要copy table to tmp table,则建议使用pt-online-schema-change来处理,比如修改列数据类型的DDL,online DDL则是需要copy table to tmp table,期间仅支持查询,不支持DML操作,这个时候,就可以使用pt-online-schema-change来处理,因为它也是拷贝临时表格,并且执行期间支持DML操作;
- 如果执行Online DDL,但是对从库的延迟非常敏感,针对需要copy table 跟rebuild table这两类DDL SQL,需要考虑是否可以在从库设置并行复制,如果不行,则优先选择pt-online-schema-change。
参考文档:https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html
pt-online-schema-change的原理解析与应用说明的更多相关文章
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
- Spring IOC设计原理解析:本文乃学习整理参考而来
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- pt-online-schema-change原理解析(转)
pt-online-schema-change原理解析 博客相关需要阅读 - zengkefu - 博客园 .pt-online-schema-change工具的使用限制: ).如果修改表有外键,除非 ...
- android黑科技系列——微信抢红包插件原理解析和开发实现
一.前言 自从几年前微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...
- android黑科技系列——Apk的加固(加壳)原理解析和实现
一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...
- 5、Spring Boot 2.x 启动原理解析
1.5 Spring Boot 启动原理解析 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏 ...
- Android中微信抢红包插件原理解析和开发实现
一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...
- 6_1.springboot2.x整合JDBC与数据源配置原理解析
1.引言 对于数据访问层,无论是SQL还是NOSQL,Spring Boot默认采用整合 Spring Data的方式进行统一处理,添加大量自动配置,屏蔽了很多设置.引入各种xxxTemplate,x ...
- EntityFramework Core表名原理解析,让我来,揭开你神秘的面纱
前言 上一节我们针对最开始抛出的异常只是进行了浅尝辄止的解析,是不是有点意犹未尽的感觉,是的,我也有这种感觉,看到这里相信您和我会有一些疑惑,要是我们接下来通过注解.Fluent APi.DbSet分 ...
- [原][Docker]特性与原理解析
Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...
随机推荐
- Python(五)编程小实例
Python(五)编程小实例 抓取网页信息,并生成txt文件内容! Python抓取网页技能--Python抓取网页就是我们常看见的网络爬虫,我们今天所要用到的就是我们Python中自带的模块,用这些 ...
- 小故事理解TCP/IP连接时的三次握手
在TCP/IP协议中,TCP协议通过三次握手建立一个可靠的连接,示意图如下: 下面通过一个小故事简单理解一下这三次握手的具体含义: 一天,快递员小客(客户端)准备去小服(服务器)家去送快递(准备与服务 ...
- Linux+Nginx+Asp.net Core部署
上篇<Docker基础入门及示例>文章介绍了Docker部署,以及相关.net core 的打包示例.这篇文章我将以oss.offical.site站点为例,主要介绍下在linux机器下完 ...
- ICC_lab总结——ICC_lab3:布局
PS:字丑,禁止转载. 做到了ICC workshop的第三个实验,理论与实践相结合,于是,先放一张总结图,这张总结图来自前面的博客,放在这里用来体现理论和实践的联系: 这个就是布局的理论部分,在IC ...
- cuda编程学习2——add
cudaMalloc()分配的指针有使用限制,设备指针的使用限制总结如下: 1.可以将其传递给在设备上执行的函数 2.可以在设备代码中使用其进行内存的读写操作 3.可以将其传递给在主机上执行的函数 4 ...
- Java异常处理总结
题记:本文为工作十年回顾总结系列之Java语言之异常处理篇,主要内容为<Thinking in Java >第四版和<Effective Java>第二版的阅读笔记,网上流传的 ...
- java 接口默认修饰符问题
package test; public interface InterfaceTest { void todo();} /** * 以下是反编译的内容,接口里的方法默认都是public的.abstr ...
- Object-C知识点
Object-C常用的知识点,以下为我在实际开发中用到的知识点,但是又想不起来,需要百度一下的知识点 1. p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: ...
- 老李推荐:第6章7节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-注入按键事件实例
老李推荐:第6章7节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-注入按键事件实例 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜 ...
- 老李分享:Android性能优化之内存泄漏2
这种创建Handler的方式会造成内存泄漏,由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理 ...