pt-tools系列:pt-online-schema-change 最佳实践

简介: pt的详细步骤 Step 1: Create the new table. Step 2: Alter the new, empty table. This should be very quick, or die if the user specified a bad alter statement.

pt的详细步骤

Step 1: Create the new table.
Step 2: Alter the new, empty table.
        This should be very quick, or die if the user specified a bad alter statement.
Step 3: Create the triggers to capture changes on the original table and apply them to the new table.
Step 4: Copy rows.
Step 5: Rename tables: orig -> old, new -> orig
Step 6: Update foreign key constraints if there are child tables.
Step 7: Drop the old table.
        DROP TABLE IF EXISTS `_xx_old`
        DROP TRIGGER IF EXISTS `pt_osc_xx_xx_del`;
        DROP TRIGGER IF EXISTS `pt_osc_xx_xx_upd`;
        DROP TRIGGER IF EXISTS `pt_osc_xx_xx_ins`;
done


一、常用参数解读

1.0 生产环境使用的参数

inception调用pt-online-schema-change,相关参数如下:

inception_osc_alter_foreign_keys_method = rebuild_constraints
inception_osc_check_alter = on
inception_osc_check_interval = 5
inception_osc_check_replication_filters = OFF
inception_osc_chunk_size = 1000
inception_osc_chunk_size_limit = 4
inception_osc_chunk_time = 1
inception_osc_critical_thread_connected = 4000
inception_osc_critical_thread_running = 300
inception_osc_drop_new_table = on
inception_osc_drop_old_table = on
inception_osc_max_lag = 3
inception_osc_max_thread_connected = 2500
inception_osc_max_thread_running = 200
inception_osc_min_table_size = 16
inception_osc_recursion_method = none

以上inception参数对应的pt-online-schema-change的命令参数如下:

pt-online-schema-change
    --alter " xx "
    --alter-foreign-keys-method=rebuild_constraints
    --check-alter=yes
    --check-interval=5
    --check-replication-filters=no
    --chunk-size=1000
    --chunk-size-limit=4
    --chunk-time=1
    --critical-load=thread_connected:4000,thread_running:300
    --max-load=thread_connected:2500,thread_running:200
    --drop-new-table=yes
    --drop-old-table=yes
    --max-lag=3
    --recursion-method=none

1.1 基本用法

  • pt-online-schema-change [OPTIONS] DSN
  • pt-online-schema-change --alter "ADD COLUMN c1 INT" D=sakila,t=actor
  • pt-online-schema-change --alter "ENGINE=InnoDB" D=sakila,t=actor

1.2 安全的pt-online-schema-change

默认情况下,pt-online-schema-change 是不会修改表的,除非你显示的指定了 --execute
pt-online-schema-change 有一系列动作来阻住一切不期望的后果发生,包括 自动检测复制,以及以下相关措施

  • 大部分情况下,pt-online-schema-change会拒绝给没有主键和唯一键的表做操作,可以参考 --alter 了解更多信息
  • 如果检测到复制过滤(ignore-db,do-db等),pt-online-schema-change会拒绝操作,可以参考 --[no]check-replication-filters 了解更多信息
  • 如果发现复制严重的厉害,那么会暂停copy数据,可以参考 --max-lag 了解更多的信息
  • 如果发现服务器负载非常高,那么也会暂停或者停止相关操作,可以参考 --max-load and --critical-load 了解更多信息
  • 该工具默认会设置 innodb_lock_wait_timeout=1 和 lock_wait_timeout=60来减少竞争 , 参考 --set-vars 了解更多信息
  • 如果有外键约束,那么禁止改表,出发你指定 --alter-foreign-keys-method.
  • Percona XtraDB Cluster中禁止修改MYISAM的表

1.3 常用参数

  • --dry-run and --execute , 这两个是互斥的参数,一个是打印,一个是执行
  • --alter

通过这个选项,就不需要alter table关键字了。 你可以通过逗号来指定多个修改操作。

* 以下列出--alter中的一些限制,大家谨记和避免

1. 原表必须要有主键或唯一键,因为delete触发器需要用到,否则会报错

2. rename子句,不允许给表重命名

2.1 不能通过删除一列,然后再新增一列的方式来完成对列的重命名操作

3. 新增字段,如果这个字段是NOT NULL,必须要指定default值,否则报错。  你必须指定默认值

4. 如果是DROP FOREIGN KEY constraint_name , 那么必须指定 _ 加上 constraint_name , 而不是 constraint_name。
    举例: CONSTRAINT `fk_foo` FOREIGN KEY (`foo_id`) REFERENCES `bar` (`foo_id`)
    你必须指定: --alter "DROP FOREIGN KEY _fk_foo"  而不是  --alter "DROP FOREIGN KEY fk_foo".

5. 必须确保数据库高于5.0版本,因为5.0版本转换MYSIAM到InnoDB会出错
  • [no]check-alter

默认yes, 给--alter 做一些检测

* 列的重命名

在之前的版本 CHANGE COLUMN name new_name 这个操作是会丢失数据的,现在的工具修复了

但是,由于pt代码并不是full-blown SQL parser,所以,你应该先 --dry-run and --print , 确认下renamed的列名是否正确,以确保无误

* 删除主键

删除主键是很危险的事情,尽量不要做这样的动作
  • --alter-foreign-keys-method

我们的规范不允许有外键,如果有外键,我们采取其他方式DDL

如何把外键引用到新表?需要特殊处理带有外键约束的表,以保证它们可以应用到新表.当重命名表的时候,外键关系会带到重命名后的表上。
该工具有两种方法,可以自动找到子表,并修改约束关系。
    auto: 在rebuild_constraints和drop_swap两种处理方式中选择一个。
    rebuild_constraints:使用 ALTER TABLE语句先删除外键约束,然后再添加.如果子表很大的话,会导致长时间的阻塞。
    drop_swap: 执行FOREIGN_KEY_CHECKS=0,禁止外键约束,删除原表,再重命名新表。这种方式很快,也不会产生阻塞,但是有风险:
            1, 在删除原表和重命名新表的短时间内,表是不存在的,程序会返回错误。
            2, 如果重命名表出现错误,也不能回滚了.因为原表已经被删除。
    none: 类似"drop_swap"的处理方式,但是它不删除原表,并且外键关系会随着重命名转到老表上面。
  • --host=xxx --user=xxx --password=xxx
连接实例信息,缩写-h xxx -u xxx -p xxx,密码可以使用参数--ask-pass 手动输入。

  • D=db_name,t=table_name
指定要ddl的数据库名和表名


  • --charset
最好设置为MySQL默认字符集: utf8
  • --check-interval
默认1秒,检测--max-lag
  • --[no]check-replication-filters

默认yes

如果发现任何服务器有 binlog_ignore_db and replicate_do_db , 那么就报错
  • --check-slave-lag
指定一个从库的DSN连接地址,如果从库超过--max-lag参数设置的值,就会暂停操作。
  • --[no]swap-tables
默认yes。交换原始表和新表,除非你禁止--[no]drop-old-table。
  • --max-lag
默认1s。
每个chunk拷贝完成后,会查看所有复制Slave的延迟情况。
要是延迟大于该值,则暂停复制数据,直到所有从的滞后小于这个值,使用Seconds_Behind_Master。
如果有任何从滞后超过此选项的值,则该工具将睡眠--check-interval指定的时间,再检查。
如果从被停止,将会永远等待,直到从开始同步,并且延迟小于该值。
如果指定--check-slave-lag,该工具只检查该服务器的延迟,而不是所有服务器。
  • --max-load
默认为Threads_running=25。
每个chunk拷贝完后,会检查SHOW GLOBAL STATUS的内容,检查指标是否超过了指定的阈值。
如果超过,则先暂停。
这里可以用逗号分隔,指定多个条件,
每个条件格式: status指标=MAX_VALUE 或者 status指标:MAX_VALUE。
如果不指定MAX_VALUE,那么工具会设置其为当前值的120%。


  • --critical-load
默认为Threads_running=50。
用法基本与--max-load类似,如果不指定MAX_VALUE,那么工具会这只其为当前值的200%。
如果超过指定值,则工具直接退出,而不是暂停。
  • --print
打印SQL语句到标准输出。指定此选项可以让你看到该工具所执行的语句,和--dry-run配合最佳。
  • --progress
复制数据的时候打印进度报告,二部分组成:第一部分是百分比,第二部分是时间。
  • --set-vars
设置MySQL变量,多个用逗号分割。
默认该工具设置的是: wait_timeout=10000 innodb_lock_wait_timeout=1 lock_wait_timeout=60
  • --recursion-method

默认是show processlist,发现从的方法,也可以是host,但需要在从上指定report_host,通过show slave hosts来找到,可以指定none来不检查Slave。
METHOD       USES
===========  ==================
processlist  SHOW PROCESSLIST
hosts        SHOW SLAVE HOSTS
dsn=DSN      DSNs from a table
none         Do not find slaves

指定none则表示不在乎从的延迟。

--pause-file

可以指定文件暂停pt-online-schema-change

二、使用限制

  • 哪些ddl是不可以做的,做了容易出错
1. 禁止创建唯一索引,会丢失数据,更加不允许添加 --alter-check=no,--check-unique-key-change=no
2. 如果原表没有主键,或者也没有唯一索引,这些表是不允许用pt做DDL的
3. 禁止对外键的表进行pt ddl
4. 禁止对表进行重命名
5. 禁止对列进行重命名,如果一定要做,也必须先print出来检测清楚列名是否正确
6. 新增字段,NOT NULL必须要指定默认值
7. 不允许删除主键
  • 由于pt触发器原理,rowcopy会产业一堆的binlog,所以做之前要检测binlog空间是否够用,也要检测数据空间多一倍表空间是否够用
  • 禁止在业务高峰期进行pt-online-schema-change操作
  • 原表不能有触发器
  • MySQL最好设置为innodb_autoinc_lock_mode=2,否则在高并发的写入情况下,很容易产生所等待以及死锁
  • master的表结构必须跟slave的表结构一致,不允许异构,否则pt-online-schema-change的原理就是会rename,然后slave不一致的表结构会被master覆盖,谨记

三、关于触发器

  • 3.0.2之前的update触发器
REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`, `c1`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`, NEW.`c1`)
  • 3.0.2之后的update触发器
BEGIN
    DELETE IGNORE FROM `lc`.`_hb_new` WHERE !(OLD.`id` <=> NEW.`id`) AND `lc`.`_hb_new`.`id` <=> OLD.`id`;
    REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`);
END
  • 原理
update触发器
    =SQL转换=> delete ignore + replace into (大于3.0.2版本)
    =SQL转换=> replace into(低于3.0.2版本,所以这个版本会有问题,如果这时候对老的主键修改,那么修改之前的值不会去掉,从而多了一些异常数据)


举例:t表中有三条数据,第一列id是主键

------
1 lc  --row1
2 lc  --row2
3 lc  --row3
------

pt-online-schema-change的原理大致四个阶段:

1. 创建临时表_t_new
2. 创建触发器
3. 老数据row copy
4. swap table


好了,我们来举个例子:

1. 创建临时表_t_new
2. 创建触发器
3. 老数据row copy
    3.1 拷贝数据row1,row2完毕
    3.2 这时候业务有一个update语句, update t set id = 10 where id=1;
    3.3 拷贝数据row3
4. swap table

这时候脑补一下原表和新表的示意图, 这时候已经执行到3.1阶段

老表
------------
1 lc  --row1
2 lc  --row2
3 lc  --row3
------------

新表
-----------
1 lc
2 lc
-----------

这时候脑补一下原表和新表的示意图, 这时候已经执行到3.3阶段

老表(update t set id = 10 where id=1)
------------
10 lc  --row1
2 lc  --row2
3 lc  --row3
------------

新表(3.0.2之前版本的触发器,没有delete映射,所以最终结果如下,跟老表相比已经不一致了,多了一条数据1,lc) , 触发器 replace into _t_new(id,name) values(10,lc)
-----------
1 lc
2 lc
10 lc
3 lc
-----------

新表(3.0.2之后版本的触发器,有delete映射,所以最终结果如下,于老表的数据一致) , 触发器 delete ignore _t_new where id = 1;replace into _t_new(id,name) values(10,lc);
-----------
2 lc
10 lc
3 lc
-----------

四、错误处理

遇到错误后,继续补充完整

目录
相关文章
|
存储 关系型数据库 MySQL
|
SQL 分布式计算 NoSQL
【SQL 审核查询平台】Archery使用介绍
【SQL 审核查询平台】Archery使用介绍
1532 0
【SQL 审核查询平台】Archery使用介绍
|
消息中间件 数据采集 监控
ELK搭建(四):监控mysql慢查询、错误日志日志
因为mysql免费、稳定以及还不错的性能,是当前市面上多数公司的数据库选择。在实际的生产环境中我们更需要及时知道数据库中的报错日志、慢日志等信息,来帮助我们进行排错和优化。 普通的到服务器上去查看日志的方式并不方便,特别是涉及到分布式部署时,因此我们需要一个统一的监控平台来实时、方便的查看这些日志数据。
1459 0
ELK搭建(四):监控mysql慢查询、错误日志日志
|
关系型数据库 MySQL 数据库
|
2月前
|
人工智能 弹性计算
2026年阿里云特惠云服务器购买规则解析:新老用户低价购买规则与避坑指南
本文介绍了阿里云当前三大类特惠云服务器的相关购买规则,覆盖新老用户不同需求。新老用户同享的经济型e实例2核2G 3M带宽仅99元/年,活动持续至2029年3月31日,每年可按99元优惠续费1次,最长可锁定5年使用权至2030年;新用户专享轻量应用服务器每日10点、15点限量秒杀,2核2G仅38元/年,2核4G低至9.9元/月或199元/年;GPU云服务器新用户首购享5折起,A10-24G等主流规格包年低至4折。文中还明确了活动对象、限购规则、退订政策等细节,以供参考。
|
3月前
|
人工智能 自然语言处理 前端开发
阿里云百炼Qwen3.7-Max模型详解:综合能力、核心优势与订阅计划全指南
Qwen3.7-Max是阿里云通义实验室联合百炼平台打造的新一代旗舰大模型,也是Qwen3.7系列中的顶配版本,定位为**智能体时代全能基座模型**。区别于仅支持单轮对话、简单指令的传统大模型,它从底层架构针对智能体运行逻辑进行深度优化,核心目标是让AI独立完成跨越数百步甚至数千步的复杂长周期任务,真正实现“无人值守式”作业。该模型依托阿里云成熟的算力基础设施与百炼全链路服务体系,不仅具备顶尖的自然语言理解、逻辑推理、多语言处理能力,还原生支持MCP(模型上下文协议),可无缝对接主流智能体框架、第三方工具、云服务组件,打破技术栈壁垒。在行业横向对比中,Qwen3.7-Max在多项权威基准测试中
598 0
|
关系型数据库 MySQL Linux
【Linux环境】centos安装mysql5.7.26报 ./mysqld: error while loading shared libraries: libaio.so.1: cannot op
【Linux环境】centos安装mysql5.7.26报 ./mysqld: error while loading shared libraries: libaio.so.1: cannot op
2364 0
|
SQL 关系型数据库 MySQL
Flink CDC 3.4 发布, 优化高频 DDL 处理,支持 Batch 模式,新增 Iceberg 支持
Apache Flink CDC 3.4.0 版本正式发布!经过4个月的开发,此版本强化了对高频表结构变更的支持,新增 batch 执行模式和 Apache Iceberg Sink 连接器,可将数据库数据全增量实时写入 Iceberg 数据湖。51位贡献者完成了259次代码提交,优化了 MySQL、MongoDB 等连接器,并修复多个缺陷。未来 3.5 版本将聚焦脏数据处理、数据限流等能力及 AI 生态对接。欢迎下载体验并提出反馈!
2162 1
Flink CDC 3.4 发布, 优化高频 DDL 处理,支持 Batch 模式,新增 Iceberg 支持
|
SQL 关系型数据库 MySQL
阿里面试:1000万级大表, 如何 加索引?
45岁老架构师尼恩在其读者交流群中分享了如何在生产环境中给大表加索引的方法。文章详细介绍了两种索引构建方式:在线模式(Online DDL)和离线模式(Offline DDL),并深入探讨了 MySQL 5.6.7 之前的“影子策略”和 pt-online-schema-change 方案,以及 MySQL 5.6.7 之后的内部 Online DDL 特性。通过这些方法,可以有效地减少 DDL 操作对业务的影响,确保数据的一致性和完整性。尼恩还提供了大量面试题和解决方案,帮助读者在面试中充分展示技术实力。