使用场景

  • 在线数据库的维护中,总会涉及到研发修改表结构的情况,修改一些小表影响很小,而修改大表时,往往影响业务的正常运转,如表数据量超过500W,1000W,甚至过亿时

在线修改大表的可能影响

  • 在线修改大表的表结构执行时间往往不可预估,一般时间较长
  • 由于修改表结构是表级锁,因此在修改表结构时,影响表写入操作
  • 如果长时间的修改表结构,中途修改失败,由于修改表结构是一个事务,因此失败后会还原表结构,在这个过程中表都是锁着不可写入
  • 修改大表结构容易导致数据库CPU、IO等性能消耗,使MySQL服务器性能降低
  • 在线修改大表结构容易导致主从延时,从而影响业务读取

介绍

pt-online-schema-change是percona公司开发的一个工具,在percona-toolkit包里面可以找到这个功能,它可以在线修改表结构。

PT-OSC工作流程:

  1. 创建一个和要执行 alter 操作的表一样的新的空表,后缀默认是new。

  2. 在新表执行alter table 语句,因为是空表,执行速度很快。

  3. 在原表中创建触发器3个触发器分别对应insert,update,delete操作。

  4. 以一定块大小从原表拷贝数据到临时表,拷贝过程中通过原表上的触发器在原表进行的写操作都会更新到新建的临时表,注意这里是Replace操作。

  5. 表明替换 将原表名table修改为 tableold, 将tablenew 表明修改为原表名table

  6. 如果有参考该表的外键,根据alter-foreign-keys-method参数的值,检测外键相关的表,做相应设置的处理

  7. 默认最后将旧原表删除

使用pt-online-schema-change执行SQL的日志

SQL语句:

# 一般修改表结构执行的语句
ALTER TABLE `tmp_task_user` ADD support tinyint(1) unsigned NOT NULL DEFAULT '1'; # 使用PT-OSC修改表结构执行的语句
sh pt.sh tmp_task_user "ADD COLUMN support tinyint(1) unsigned NOT NULL DEFAULT '1'" tmp_task_user
ADD COLUMN support tinyint(1) unsigned NOT NULL DEFAULT '1'
No slaves found. See --recursion-method if host h=127.0.0.1,P=3306 has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
Operation, tries, wait:
analyze_table, 10, 1
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Altering `test_db`.`tmp_task_user`...
Creating new table...
Created new table test_db._tmp_task_user_new OK.
Altering new table...
Altered `test_db`.`_tmp_task_user_new` OK.
2018-05-14T18:14:21 Creating triggers...
2018-05-14T18:14:21 Created triggers OK.
2018-05-14T18:14:21 Copying approximately 6 rows...
2018-05-14T18:14:21 Copied rows OK.
2018-05-14T18:14:21 Analyzing new table...
2018-05-14T18:14:21 Swapping tables...
2018-05-14T18:14:21 Swapped original and new tables OK.
2018-05-14T18:14:21 Dropping old table...
2018-05-14T18:14:21 Dropped old table `test_db`.`_tmp_task_user_old` OK.
2018-05-14T18:14:21 Dropping triggers...
2018-05-14T18:14:21 Dropped triggers OK.
Successfully altered `test_db`.`tmp_task_user`.

好处:

  • 降低主从延时的风险
  • 可以限速、限资源,避免操作时MySQL负载过高

建议:

  • 在业务低峰期做,将影响降到最低

安装

1.去官网下载对应的版本,官网下载地址:https://www.percona.com/downl...

2.下载解压之后就可以看到pt-online-schema-change

3.该工具需要一些依赖包,直接执行不成功时一般会有提示,这里可以提前yum安装

yum install perl-DBI
yum install perl-DBD-MySQL
yum install perl-Time-HiRes
yum install perl-IO-Socket-SSL

使用

1.参数

./bin/pt-online-schema-change --help 可以查看参数的使用,我们只是要修改个表结构,只需要知道几个简单的参数就可以了

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

2.为避免每次都要输入一堆参数,写个脚本复用一下,pt.sh

#!/bin/bash

table=$1
alter_conment=$2 cnn_host='127.0.0.1'
cnn_user='user'
cnn_pwd='password'
cnn_db='database_name' echo "$table"
echo "$alter_conment"
/root/percona-toolkit-2.2.19/bin/pt-online-schema-change --charset=utf8 --no-version-check --host=${cnn_host} P=3306 --user=${cnn_user} --password=${cnn_pwd} D=${cnn_db} t=$table --alter "${alter_conment}" --execute

3.添加表字段

ALTER TABLE `tb_test` ADD COLUMN `column1` tinyint(4) DEFAULT NULL;
# 那么使用pt-online-schema-change则可以这样写
sh pt.sh tb_test "ADD COLUMN column1 tinyint(4) DEFAULT NULL"

4.修改表字段

ALTER TABLE `tb_test` MODIFY COLUMN `num` int(11) unsigned NOT NULL DEFAULT '0';

# pt-online-schema-change工具:
sh pt.sh tb_test "MODIFY COLUMN num int(11) unsigned NOT NULL DEFAULT '0'"

5.修改表字段名

ALTER TABLE `tb_test` CHANGE COLUMN age adress varchar(30);
# pt-online-schema-change工具:
sh pt.sh tb_test "CHANGE COLUMN age address varchar(30)"

6.添加索引

ALTER TABLE `tb_test` ADD INDEX idx_address(address);
# pt-online-schema-change工具:
sh pt.sh tb_test "ADD INDEX idx_address(address)"

其他

  • pt-online-schema-change工具还有很多其他的参数,可以有很多限制,比如限制CPU、线程数量、从库状态等等,不过我做过一个超过6000W表的结构修改,发现几乎不影响性能,很稳定很流畅的就修改了表结构,所以,对以上常规参数的使用基本能满足业务
  • 一定要在业务低峰期做,这样才能确保万无一失

文档

1.官方参考:https://www.percona.com/doc/p...

2.官方下载:https://www.percona.com/downl...

工具学习

1. pt-osc之工作流程

1、检查更改表是否有主键或唯一索引,是否有触发器

2、检查修改表的表结构,创建一个临时表,在新表上执行ALTER TABLE语句

3、在源表上创建三个触发器分别对于INSERT UPDATE DELETE操作

4、从源表拷贝数据到临时表,在拷贝过程中,对源表的更新操作会写入到新建表中

5、将临时表和源表rename(需要元数据修改锁,需要短时间锁表)

6、删除源表和触发器,完成表结构的修改。

2. pt-osc之工具限制

1、源表必须有主键或唯一索引,如果没有工具将停止工作

2、如果线上的复制环境过滤器操作过于复杂,工具将无法工作

3、如果开启复制延迟检查,但主从延迟时,工具将暂停数据拷贝工作

4、如果开启主服务器负载检查,但主服务器负载较高时,工具将暂停操作

5、当表使用外键时,如果未使用--alter-foreign-keys-method参数,工具将无法执行

6、只支持Innodb存储引擎表,且要求服务器上有该表1倍以上的空闲空间。

3. pt-osc之唯一索引

使用pt-osc创建唯一索引时,会造成数据丢失,需谨慎操作:

1、当表中要建立唯一索引的数据列上存在重复数据,则部分重复数据会丢失

2、如果创建过程中插入新数据,新数据与原数据库存在重复,则原数据丢失

丢失原因:

由于INSERT和UPDATE触发器使用REPLCAE INTO的方式更新新表数据,而新表中包含唯一索引,导致REPLACE INTO操作转换成DELETE+INSERT操作,将已存在于新表中的重复记录删除,再插入当前记录,最终导致数据丢失。

4. pt-osc之拷贝数据

在拷贝数据过程中,工具会把数据按照主键或唯一键进行拆分,限制每次拷贝数据的行数以保证拷贝进行不过多消耗服务器资源。为保证源表和目标表数据相同,采用LOCK IN SHARE MODE来获取要拷贝数据段的最新数据并对数据加共享锁组织其他回话修改数据,

采用LOW_PRIORITY IGNORE来将数据插入到新表中, 关键字LOW_PRIORIT使得插入操作会等待其他访问该表的操作完成会再执行,

关键字INGORE使得表中出现主键或唯一索引键重复时新数据被忽略而不会被插入。

对表testdb1.tb1001进行修改时的数据拷贝脚本:

先获取下一次拷贝数据的边界,强制索引可以有效避免执行计划出现问题

SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `testdb1`.`tb1001` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= '8394306')) ORDER BY `id` LIMIT 22256, 2 /*next chunk boundary*/

通过拷贝数据的边界限制,防止单次拷贝过多数据而长时间阻塞其他回话

INSERT LOW_PRIORITY IGNORE INTO `testdb1`.`_tb1001_new` (`id`, `c1`, `c6`) SELECT `id`, `c1`, `c6` FROM `testdb1`.`tb1001` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= '8394306')) AND ((`id` <= '8416562')) LOCK IN SHARE MODE /*pt-online-schema-change 14648 copy nibble*/

5. pt-osc之触发器

pt-osc工具在源表上创建三个AFTER触发器分别对于INSERT UPDATE DELETE操作,DELETE触发器使用DELETE IGNORE来保证源表和新表的数据都被删除, 而INSERT和UPDATE触发器使用REPLACE INTO来保证新表数据和源表数据一致。

由于MySQL限制相同类型的触发器只能有一个,因此需要在运行前检查源表上是否有触发器,为保证删除和更新效率和方便和将源表数据进行分片处理,因此要求表上有主键或唯一索引。

6. pt-osc之主机性能影响

为避免过度影响主机性能,pt-osc工具通过以下几个方面来限制:

1、通过参数chunk-size和chunk-time控制每次拷贝数据大小

2、通过参数max-load来检查主机当前压力,每次chunk拷贝完成后,都会运行SHOW GLOBAL STATUS LIKE 'Threads_running' 命令检查当前正在运行的Threads数量,默认Threads_running=25,如果未指定最大值,则会取当前值的120%作为最大值,如果超过阀值则会暂停数据拷贝

7. pt-osc之从库复制延迟

对于复制延迟比较敏感的业务,可以通过下面参数来控制复制延迟:

--max-log

默认为1s,每个chunks拷贝完成后,会查看check-slave-lag参数所指定的从库的延迟信息,如果超过max-log的阀值,则暂停复制数据,直到复制延迟小于max-log的阀值。检查复制延迟信息依赖于SHOW SLAVE STATUS语句中返回的Seconds_Behind_Master列的值。

--check-interval

当出现复制延迟暂停复制数据后,按照check-interval指定的时间进行周期检查复制延迟,直到延迟时间低于max-log阀值,然后恢复数据拷贝

--check-slave-lag

需要检查复制延迟的从库IP

如果指定check-slave-lag参数,且从库无法正常连接或从库IO线程和SQL线程停止,会认为主从存在延迟,导致复制数据操作一直暂停。

如果未指定check-slave-lag参数,默认还是会检查从库的延迟,但复制延迟不会导致数据复制暂停。

8. pt-osc之chunk设置

在pt-osc的帮助文档中,关于chunk的参数有如下:

--chunk-index=s Prefer this index for chunking tables

--chunk-index-columns=i Use only this many left-most columns of a --chunk-index

--chunk-size=z Number of rows to select for each chunk copied (default 1000)

--chunk-size-limit=f Do not copy chunks this much larger than the desired chunk size (default 4.0)

--chunk-time=f Adjust the chunk size dynamically so each data-copy query takes this long to execute (default 0.5)

当chunk-size和chunk-time两者都未指定时,chunk-size默认值为1000,chunk-time默认值为0.5S,第一次按照chunk-size来进行数据复制,然后根据第一次复制的时间动态调整chumk-size的大小,以适应服务器的性能变化,如上一次复制1000行消耗0.1S,则下次动态调整chumk-size为5000。

如果明确指定chumk-size的值或将chunk-time指定为0,则每次都按照chunk-size复制数据。

9. pt-osc之alter语句限制

1、不需要包含alter table关键字,可以包含多个修改操作,使用逗号分开,如"drop clolumn c1, add column c2 int"

2、不支持rename语句来对表进行重命名操作

3、不支持对索引进行重命名操作

4、如果删除外键,需要对外键名加下划线,如删除外键fk_uid, 修改语句为"DROP FOREIGN KEY _fk_uid"

10.pt-osc之命令模板

--execute表示执行

--dry-run表示只进行模拟测试

表名只能使用参数t来设置,没有长参数

pt-online-schema-change \
--host="127.0.0.1" \
--port=3358 \
--user="root" \
--password="root@root" \
--charset="utf8" \
--max-lag=10 \
--check-salve-lag='xxx.xxx.xxx.xxx' \
--recursion-method="hosts" \
--check-interval=2 \
--database="testdb1" \
t="tb001" \
--alter="add column c4 int" \
--execute

11. pt-osc之命令输出

上面命令执行输出如下:

No slaves found. See --recursion-method if host 171DB166 has slaves.
Will check slave lag on:
170DB166
Operation, tries, wait:
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Altering `testdb1`.`tb001`...
Creating new table...
Created new table testdb1._tb001_new OK.
Altering new table...
Altered `testdb1`.`_tb001_new` OK.
2016-04-28T23:18:04 Creating triggers...
2016-04-28T23:18:04 Created triggers OK.
2016-04-28T23:18:04 Copying approximately 1 rows...
2016-04-28T23:18:04 Copied rows OK.
2016-04-28T23:18:04 Swapping tables...
2016-04-28T23:18:04 Swapped original and new tables OK.
2016-04-28T23:18:04 Dropping old table...
2016-04-28T23:18:04 Dropped old table `testdb1`.`_tb001_old` OK.
2016-04-28T23:18:04 Dropping triggers...
2016-04-28T23:18:04 Dropped triggers OK.
Successfully altered `testdb1`.`tb001`.

在线修改大表结构pt-online-schema-change的更多相关文章

  1. pt-online-schema-change工具使用教程(在线修改大表结构)

    percona-toolkit中pt-online-schema-change工具安装和使用 pt-online-schema-change介绍 使用场景:在线修改大表结构 在线数据库的维护中,总会涉 ...

  2. dbms_redefinition在线重定义表结构 可以在表分区的时候使用

    dbms_redefinition在线重定义表结构 (2013-08-29 22:52:58) 转载▼ 标签: dbms_redefinition 非分区表转换成分区表 王显伟 在线重定义表结构 在线 ...

  3. dbms_redefinition在线重定义表结构

    dbms_redefinition在线重定义表结构 (2013-08-29 22:52:58) 转载▼ 标签: dbms_redefinition 非分区表转换成分区表 王显伟 在线重定义表结构 在线 ...

  4. mysql数据库连接状态,不要做修改数据库表结构的操作;数据库迁移操作;

    在开发过程中,python的flask框架使用sqlalmysql连接mysql数据库. 在程序连接数据量过程中,不要修改数据表的结构.比如在连接状态中使用下面的软件修改数据表结构,这个软件立即就会卡 ...

  5. [转载]github在线更改mysql表结构工具gh-ost

    GitHub正式宣布以开源的方式发布gh-ost:GitHub的MySQL无触发器在线更改表定义工具! gh-ost是GitHub最近几个月开发出来的,目的是解决一个经常碰到的问题:不断变化的产品需求 ...

  6. 5、ABPZero系列教程之拼多多卖家工具 修改User表结构

    毕竟这个框架是外国人开发的,对于我们国人来说还是有些地方并不合适,就好比如注册时需要填写名字.姓氏一样,今天要说的就是如何去掉这2个字段. 先看如下修改完成的效果图 User表结构修改 修改User类 ...

  7. EF5修改edmx表结构保存后不自动更新tt (转)

    http://blog.csdn.net/panderman/article/details/8172968 不知道这算不算一个bug,当你新建一个从数据库生成的edmx时,他能正确的生成所有的tt文 ...

  8. MySQL修改,表结构大幅修改

    ------------------create table t_video_file_temp( video_id bigint not null comment '视频Id', file_md5 ...

  9. Magento模块升级修改数据库表结构

    Magento支持在模块中创建.删除.更新数据库表及字段.通过该方式,在插件开发的过程中,添加和修改字段变成了一件非常轻松的事情.只需要修改模块的版本号,同时在文件中添加一个符合命名规则的脚本就可以了 ...

随机推荐

  1. Android 造炫目的圆形菜单 秒秒钟高仿建行圆形菜单

    1.概述 今天打开建行看存款,一看伤心欲绝,再看:我擦,这个圆形菜单挺炫.于是,为了掩盖我悲痛的心情,我决定是实现这个效果.好了,其实还有个原因,记得我初学android那会我做的应用被鄙视了,说我的 ...

  2. [CSP-S模拟测试]:平方数(数学+哈希)

    题目传送门(内部题137) 输入格式 第一行,一个正整数$n$. 第二行$n$个正整数$a_1\sim a_n$. 输出格式 输出一个整数,为满足条件的二元组个数. 样例 样例输入: 51 2 3 4 ...

  3. IDEA 无法自动导入相关Maven jar包

    仔细看看项目右边有个很骚的"Maven Projects"按钮,点击一下 再点击这个刷新按钮,现在知道技术为何物了吗?

  4. spring-sevlet简单配置

    <<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www ...

  5. 第七周课程总结 & 实验报告(五)

    第七周课程总结 一.抽象类与接口的应用 1.实例化 2.实际应用 ---模板设计(抽象类) ---制定标准(接口) 3.设计模式 ---工厂设计 ---代理设计 ---适配器设计 二.抽象类与接口之间 ...

  6. /usr/bin/env python no such file or directory: dos格式导致的!

    最近修改了几个python文件,发现在linux上只能用python file来执行,直接./file提示错误"no such file or directory",而脚本是用&q ...

  7. leetcode-easy-string-7 Reverse Integer

    mycode class Solution(object): def reverse(self, x): """ :type x: int :rtype: int &qu ...

  8. JS - 获取函数的参数名称

    看 Angular 依赖注入时发现的神奇的操作,实现原理是 Function.prototype.toString() 得到函数的字符串然后用正则判断. 参见 javascript - How to ...

  9. 在 manifest 和代码中如何注册和使用 BroadcastReceiver?

    在清单文件中注册广播接收者称为静态注册,在代码中注册称为动态注册.静态注册的广播接收者只要 app 在系统中运行则一直可以接收到广播消息,动态注册的广播接收者当注册的 Activity 或者 Serv ...

  10. 【MAC】安装chrome浏览器

    step1:下载dmg安装包 chrome下载地址 点击[下载Chrome] step2:安装chrome 下载好googlechrome.dmg文件后,像其它程序一样安装就可以了 打开访达--> ...