温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何理解gh-ost

发布时间:2021-10-09 14:24:04 来源:亿速云 阅读:293 作者:柒染 栏目:MySQL数据库

如何理解gh-ost,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

    公司内部一直使用的online ddl工具是pt-online-schema-change,今天准备尝试一下另外一个工具gh-ost。

    gh-ost 是 gitHub,s Online Schema Transmogrifier/Transfigurator/Transformer/Thingy 的缩写,意思是 GitHub 的在线表定义转换器。

    我对gh-ost的感兴趣的原因是gh-ost可随时暂停。如果变更过程发现主库性能受影响,可以立刻停止拉binlog,停止应用 binlog,停止移动行数据,等性能稳定之后再继续;另外,gh-ost不依赖触发器,这是和pt-osc的最大区别。

大致的工作原理:

只以主库模式介绍:

如何理解gh-ost

1、 gh-ost 首先连接到主库上,根据 alter 语句创建幽灵表_tablename_gho;
  
2、 然后gh-ost作为一个备库连接到主库上,一边在主库上拷贝已有的数据到幽灵表,
一边从主库上拉取增量数据的 binlog,然后不断的把 binlog 应用回主库幽灵表;
  
3、 等待全部数据同步完成,进行cut-over,即进行幽灵表和原表切换。cut-over是最后一步,
锁住主库的源表,等待binlog应用完毕,然后替换gh-ost幽灵表为源表。gh-ost在执行中,
会在原本的binlog event里面增加hint和心跳包,用来控制整个流程的进度,检测状态等。

下载安装

    从 github 发布地址下载最新的 binary 包:https://github.com/github/gh-ost/releases

    解压后就一个 gh-ost 二进制文件。

 tar -xvf  gh-ost-binary-linux-20190214020851.tar.gz
 cp gh-ost /usr/bin

常用命令组合

只以主库模式介绍,上生产可以直接用:

gh-ost \
 --max-load=Threads_running=50 \
 --critical-load=Threads_running=80 \
 --critical-load-interval-millis=5000 \
 --max-lag-millis=1500 \
 --chunk-size=1000 \
 --ok-to-drop-table \
 --initially-drop-ghost-table \
 --initially-drop-socket-file \
 --host=172.18.6.2 \
 --port=3306 \
 --user="chenzhixin" \
 --password="123456"\
 --database="test" \
 --table="user100w"  \
 --verbose \
 --alter="add column test_field6 varchar(256) default '';" \
 --cut-over-lock-timeout-seconds=1 \
 --dml-batch-size=10 \
 --exact-rowcount  \
 --serve-socket-file=/tmp/ghost.sock \
 --panic-flag-file=/tmp/ghost.panic.flag  \
 --allow-on-master \
 --execute
 
 ##########  特别提醒!!!!!!############################
 下面这个参数有需要再加,加了它就不会自动切换源表和幽灵表,需要手工删除/tmp/ghost.postpone.flag
 文件后,才会发生自动切换,请理解该参数含义。
 --postpone-cut-over-flag-file=/tmp/ghost.postpone.flag

    操作过程中会生成两个中间状态的表 _tablename_ghc和_tablename_gho,其中 _tablename_ghc 是记录gh-ost 执行过程的表,_tablename_gho 是目标表,也即应用ddl语句的幽灵表_tablename_gho。

    执行上述的gh-ost命令过程中,会看到如下的_user100w_ghc的执行过程表,和_user100w_gho幽灵表、

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| _user100w_ghc  |
| _user100w_gho  |
| fruits         |
| test_timestamp |
| user100w       |
+----------------+
5 rows in set (0.00 sec)

    解释:

--max-load=Threads_running=50 
  表面如果在执行gh-ost的过程中出现Threads_running=50则暂停gh-ost的执行
--critical-load=Threads_running=80 
 表明执行过程中出现Threads_running达到80则终止gh-ost的执行
--critical-load-interval-millis 当值为0时,当达到-critical-load,gh-ost立即退出。当值不为0时,当达到-critical-load,gh-ost会在-critical-load-interval-millis秒数后,再次进行检查,再次检查依旧达到-critical-load,gh-ost将会退出
--max-lag-millis
  会监控从库的主从延迟情况,如果延迟秒数超过这个阀值,row copy不会退出,等待延迟秒数低于这个阀值继续迁移。
--ok-to-drop-table
 go-ost 执行完以后是否删除老表,加上此参数会自动删除老表。默认不删除老表,会存在_tablename_del表
--initially-drop-ghost-table
 gh-ost 执行前会创建两张 xx_ghc 和 xx_gho 表,如果这两张表存在,且加上了这个参数,那么会自动删除原 gh 表,从新创建,否则退出。xx_gho 表相当于老表的全量备份,xx_ghc 表数据是数据更改日志,理解成增量备份。
--initially-drop-socket-file
 gh-ost 执行时会创建 socket 文件,退出时不会删除,下次执行 gh-ost 时会报错,加上这个参数会删除老的 socket 文件,重新创建。
--throttle-flag-file
 此文件存在时操作暂停,删除文件操作会继续。
--verbose
 执行过程输出日志
--chunk-size
 迁移过程是一步步分批次完成的,这个参数是指事务每次提交的行数,默认是 1000。
--max-lag-millis
 会监控从库的主从延迟情况,如果延迟秒数超过这个阀值,迁移不会退出,等待延迟秒数低于这个阀值继续迁移。
--max-lag-millis
 会监控从库的主从延迟情况,如果延迟秒数超过这个阀值,迁移不会退出,等待延迟秒数低于这个阀值继续迁移
--throttle-control-replica
  和--max-lag-millis 参数相结合,这个参数指定主从延迟的数据库实例。
--cut-over-lock-timeout-seconds      
  gh-ost在cut-over阶段最大的锁等待时间,当锁超时时,gh-ost的cut-over将重试。(默认值:3)
--allow-on-master
 整个迁移所有操作在主库上执行
--dml-batch-size   
  在单个事务中应用DML事件的批量大小(范围1-100)(默认值为10)
--exact-rowcount 
  准确统计表行数(使用select count(*)的方式),得到更准确的预估时间。
--postpone-cut-over-flag-file 
  当这个文件存在的时候,gh-ost的cut-over阶段将会被推迟,数据仍然在复制,直到该文件被删除。
--throttle-flag-file string
  当该文件被创建后,gh-ost操作立即停止。该参数适合控制单个gh-ost操作。-throttle-additional-flag-file string适合控制多个gh-ost操作。

进度提示

    执行gh-ost中,会有输出信息,具体解释如下:

Copy: 27000/58707 46.0%;58707指需要迁移总行数,27000指已经迁移的行数,46%指迁移完成的百分比。
Applied: 0,指在二进制日志中处理的event数量。在上面的例子中,迁移表没有流量,因此没有被处理日志event。
Backlog: 0/1000,表示我们在读取二进制日志方面表现良好,在二进制日志队列中没有任何积压(Backlog)事件。
Backlog: 7/1000,当复制行时,在二进制日志中积压了一些事件,并且需要应用。
Backlog: 1000/1000,表示我们的1000个事件的缓冲区已满(程序写死的1000个事件缓冲区,低版本是100个),此时就注意binlog写入量非常大,gh-ost处理不过来event了,可能需要暂停binlog读取,需要优先应用缓冲区的事件。
streamer: shvm-5-39.000040:338912890;表示当前已经应用到binlog文件位置

控制gh-ost的过程

#首先要安装socat工具

yum install socat -y

    注意:上面gh-ost里面配置的--serve-socket-file=/tmp/ghost.sock,下面就用到了。

    gh-ost 可以通过 unix socket 文件的方式来监听请求,DBA 可以在gh-ost命令运行后更改相应的参数进行限流操作等。

#暂停

echo throttle | socat - /tmp/ghost.sock

#恢复

echo no-throttle | socat - /tmp/ghost.sock

#终止

对应panic-flag-file参数文件,当tmp目录存在该文件立即停止
touch /tmp/ghost.panic.flag

#延迟切换(cut-over阶段)

--postpone-cut-over-flag-file=/tmp/ghost.postpone.flag
当设置该参数时cut-over一直延迟源表和幽灵表的切换,直到你删除该文件才进行切换。

适用场景:

你发起了一次修改操作,然后估计完成时间是凌晨 2 点钟,可是你又非常关心最后的切换操作,
非常想看着它切换,这可怎么办?只需要一个标志位文件就可以告诉 gh-ost 推迟切换了,
这样 gh-ost 会只做完拷贝数据的操作,但不会切换表。它还会仍然继续同步数据,
保持幽灵表的数据处于同步状态。等第二天早上你回到办公室之后,
删除标志位文件或者向gh-ost发送命令echo unpostpone,它就会做切换了。
我们不希望软件强迫我们看着它做事情,它应该把我们解放出来,让人去做人该做的事。

#在线修改限速参数

echo max-load=Threads_connected=200  | socat - /tmp/ghost.sock
echo max-load=Thread_running=3 | socat - /tmp/ghost.sock
echo chunk-size=100 | socat - /tmp/ghost.sock
echo max-lag-millis=200 | socat - /tmp/ghost.sock

适用场景:

当你执行了 gh-ost 之后,也许你会看见主库的负载变高了,那你可以发出暂停命令。
用 echo throttle 命令生成一个文件,看看主库的负载会不会又变得正常。试一下这些命令,
你就可以知道你可以怎样控制它的行为,你的心里就会安定许多。

gh-ost的限制

    凡事有利必有弊,人不可能把所有好事都占有,下面是gh-ost的几个限制:

    1、不支持没有主键或者唯一索引的表

    2、不支持有外键约束的表(主表和子表都不支持)

    3、不支持表上有触发器

    5、表上存在大量写入的时候,gh-ost可能永远也完成不了

    经过测试:当写入QPS 5000以上,gh-ost无法完成任务,其原因是apply binlog是单线程,可以理解为slave,当原表写入量巨大时(QPS=5000以上),一直在应用日志,而gh-ost设计是binlog应用优先级高于row copy,所以我们看到row copy进度一直没变,这样如果原表一直压力这么大,那么gh-ost DDL将无法完成。经过在s3710机器上测试如果原表写入的QPS大于5000将大概率出现此情况,小于5000的话没问题。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI