此工具要解决的问题
Alter table操作会锁表并造成读写阻塞,对于千万级别大表,持续时间可达数小时,在online情况下,势必造成服务不可用以及用户体验退化的问题。当然,官方也有这方面的考虑,所以提供了像`ALTER ONLINE TABLE`, `ALTER TABLE ..., ALGORITHM=INSTANT, LOCK=NONE`这样的命令来解决在线更新表结构的问题。
但是,官方提供的方法,在某些场景下不起作用,比如修改字段,修改索引,添加索引等。 这时候就需要用到第三方工具 pt-online-schema-change 了。
原理,风险,局限性
操作前请认真阅读官方文档如何操作
比如删除demoTable的索引myIndex (**其实删除索引不需要用此工具,使用**`ALTER TABLE tripadvisor_reviews DROP INDEX locationId, ALGORITHM=INPLACE;`**速度非常快**)- 先用--dry-run验证命令合法性
`pt-online-schema-change --socket=/run/mysqld/mysqld.sock --alter "DROP INDEX myIndex" D=demoDB, t=demoTable --print --dry-run`
- 通过验证后再用--execute代替--dry-run落地执行
`pt-online-schema-change --socket=/run/mysqld/mysqld.sock --alter "DROP INDEX myIndex" D=demoDB, t=demoTable --print --execute`
修改改字段示例:
`pt-online-schema-change --socket=/run/mysqld/mysqld.sock --alter "CHANGE myfield myfield VARCHAR(5) NOT NULL DEFAULT ''" D=demoDB,t=demoTable --print --dry-run`
添加字段与索引示例:
`pt-online-schema-change --socket=/run/mysqld/mysqld.sock --alter "ADD myfieldCHAR(5) NOT NULL DEFAULT '', ADD INDEX(myfield)" D=demoDB,t=demoTable --print --dry-run`
修改引擎:
`pt-online-schema-change --alter "ENGINE=InnoDB" D=demoDB, t=demoTable --dry-run`
删除字段:
`pt-online-schema-change --alter "DROP myColumn" D=demoDB, t=demoTable --dry-run`
由于此工具需要在原始表上创建triggers,所以当原始表本身含有triggers时要如下处理:
1. mysql5.7.1及以下版本(MariaDB 10.2.2)只支持一个event对应一个trigger, 那么必须得删除原始表的triggers, 待数据copy结束之后,重新在新表上手动创建这些triggers.
2. mysql5.7.2及以上版本(MariaDb 10.2.3)支持一个event对应多个triggers, 那么在运行此工具时加上参数`--preserve-triggers` 即可
此工具运行耗时长,建议使用screen开启虚拟终端,在虚拟终端中执行它。
#
#附:screen用法
`screen -R myTermi` #开启一个名为myTermi的终端,如果存在就直接进入
`screen -S myTermi` #开启一个名为myTermi的虚拟终端,有可能重名
**进入虚拟终端之后,如果要回到主终端,有两种情况:**
- 退出终端,但保持后台运行: `ctrl+a` 再按 `d`
- 退出终端不保持后台运行:`ctrl+a` 再按 `k`. (在虚拟终端中输入exit一样的效果)
**重新回到虚拟终端的方法:**
- 先使用`screen -ls` 查看已创建的虚拟终端(结果的第一列是由Pid和name组成)
- 使用`screen -r/-R [Pid/name]` 都可以回到虚拟终端,但这对于状态为Detached的虚拟终端才有用。
- 如果虚拟终端的状态是Attached(比如网络中断导致没有使用ctr+a, d命令退出), 那么使用 -R 并不能重新进入,而是会新创建一个同名虚拟终端。 -r 也无法进入。
- 此时需要使用 `screen -d [pid/name]`将对应的Attached状态变为Detached状态就可以了。
**如何检测是否在虚拟终端中**
- 方法一,在screen session中 使用命令`echo $STY`, 它会输出screen session的名字,否则是空值
- 方法二,`ctrl + a` 再 `ctrl + t`, 如果在screen session中它会输出日期,否则没有任何反应。