在之前,我分享过一次pt-online-schema-change在线DDL的工具实践记录,在实际使用过程中,发现部门的很多老系统大量使用了触发器,从而无法使用这个工具,非常遗憾!导致很多DDL变更都必须压到空闲时候做,比如凌晨,非常苦逼。

咨询了做DBA的老同事,他将gh-ost推荐给我,基于golang语言,是github开源的一个DDL工具,gh-ost是gitHub,s Online Schema Transmogrifier/Transfigurator/Transformer/Thingy的缩写,意思是GitHub的在线表定义转换器。============  分割线之间内容摘自网络  ============

gh-ost有如下特点:

无触发器

轻量级

可暂停

动态可控

可审计

可测试

可靠

无触发器

gh-ost不使用触发器,它跟踪二进制日志文件,在对原始表的修改提交之后,用异步方式把这修改内容应用到临时表中去。

gh-ost希望二进制文件使用基于行的日志格式,但这并不表示如果主库上使用的是基于语句的日志格式,就不能用它来在线修改表定义了。事实上,我们常用的方式是用一个从库把日志的语句模式转成行模式,再从这个从库上去读日志。搭一个这样的从库并不复杂。

轻量级

因为不需要使用触发器,gh-ost把修改表定义的负载和正常的业务负载解耦开了。它不需要考虑被修改的表上的并发操作和竞争等,这些在二进制日志中都被序列化了,gh-ost只操作临时表,完全与原始表不相干。事实上,gh-ost也把行拷贝的写操作与二进制日志的写操作序列化了,这样,对主库来说只是有一条连接在顺序的向临时表中不断写入数据,这样的行为与常见的ETL相当不同。

可暂停

因为所有写操作都是gh-ost生成的,而读取二进制文件本身就是一个异步操作,所以在暂停时,gh-ost是完全可以把所有对主库的写操作全都暂停的。暂停就意味着对主库没有写入和更新。不过gh-ost也有一张内部状态跟踪表,即使在暂停状态下也会向那张表中不断写入心跳信息,写入量可以忽略不计。

gh-ost提供了比简单的暂停更多的功能,除了暂停之外还可以做:

负载:与pt-online-schema-change相近的一个功能,用户可以设置MySQL指标的阈值,比如设置Threads_running=30。

复制延迟:gh-ost内置了心跳功能来检查复制延迟。用户可以指定查看哪个从库的延迟,gh-ost默认是直接查看它连上的那个从库。

命令:用户可以写一些命令,根据输出结果来决定要不要开始操作。比如:SELECT HOUR(NOW()) BETWEEN 8 and 17.

上述所有指标即使在修改表定义的过程中也可以动态修改。

标志位文件:生成一个标志位文件,gh-ost就会立刻暂停。删除文件,gh-ost又会恢复工作。

用户命令:通过网络连上gh-ost,通过命令让它暂停。

动态可控

如果别的工具在修改过程中产生了比较高的负载,DBA只好把它停掉再修改配置,比如把一次拷贝的数据量改小些,然后再从头开始修改过程。这样的反复操作代价非常大。

gh-ost通过监听TCP或者unix socket文件来获取命令。即使有正在进行中的修改工作,用户也可以向gh-ost发出命令修改配置,比如可以这样做:

echo throttle | socat - /tmp/gh-ost.sock:这是暂停命令。也可以输入no-throttle

修改运行参数,gh-ost可以接受这样的修改方式来改变它的行为:chunk-size=1500, max-lag-millis=2000, max-load=Thread_running=30

可审计

用上面所说的相同接口也可以查看gh-ost的状态,查看当前任务进度、主要配置参数、相关MySQL实例的情况等。这些信息通过网络发送命令就可以得到,因此就给了运维人员极大的灵活性,如果是使用别的工具的话一般只能是通过共享屏幕或者不断跟踪日志文件最新内容。

可测试

读取二进制文件内容的操作完全不会增加主库的负载,在从库上做修改表结构的操作也和在主库上做是非常相象的(当然并不完全一样,但主要来说还是差不多的)。

gh-ost自带了--test-on-replica选项来支持测试功能,它允许你在从库上运行起修改表结构操作,在操作结束时会暂停主从复制,让两张表都处于同步、就绪状态,然后切换表、再切换回来。这样就可以让用户从容不迫地对两张表进行检查和对比。

我们在GitHub是这样在生产环境测试gh-ost的:我们有许多个指定的生产从库,在上面不提供服务,只是周而复始地不断地把所有表定义都改来改去。对于我们生产环境地每一张表,小到空表,大到几百GB,都会通过修改存储引擎的方式来进行修改(engine=innodb),这样并不会真正修改表结构。在每一次这样的修改操作最后我们都会停掉主从复制,再把原始表和临时表的全量数据都各做一次校验和,然后比较两个校验和,要求它们是一致的。然后我们恢复主从复制,再继续测试下一张表。我们生产环境的每一张表都这样用gh-ost在从库上做过好多次修改测试。

可靠的

所有上述讲到的和没讲到的内容,都是为了让你对gh-ost的能力建立信任。毕竟,大家在做这件事的时候已经使用类似工具做了好多年,而gh-ost只是一个新工具。

我们在从库上对gh-ost进行测试,在去主库上做第一次真正改动之前我们在从库上成功地试了几千次。所以,请你也在从库上开始测试,验证数据是完好无损的,然后再把它用到生产环境。我们希望你可以放手去试。

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

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

谈到估计完成时间,--exact-rowcount选项非常有用。在最开始时要在目标表上做个代价比较大的SELECT COUNT(*)操作查出具体要拷多少行数据,gh-ost就会对它要做多少工作有了一个比较准确的估计。接下来在拷贝的过程中,它会不断地尝试更新这个估计值。因为预计完成的时间点总是会不断变化,所以已经完成的百分比就反而比较精确。如果你也曾经有过非常痛苦的经历,看着已经完成99%了可是剩下的一点操作却继续了一个小时也没完,你就会非常喜欢我们提供的这个功能。

gh-ost工作模式【要着重看】

gh-ost工作时可以连上多个MySQL实例,同时也把自己以从库的方式连上其中一个实例来获取二进制日志事件。根据你的配置、数据库集群架构和你想在哪里执行修改操作,可以有许多种不同的工作模式。

模式一、连上从库,在主库上修改

这是gh-ost默认的工作模式,它会查看从库情况,找到集群的主库并且连接上去。修改操作的具体步骤是:

在主库上读写行数据;

在从库上读取二进制日志事件,将变更应用到主库上;

在从库上查看表格式、字段、主键、总行数等;

在从库上读取gh-ost内部事件日志(比如心跳);

在主库上完成表切换;

如果主库的二进制日志格式是Statement,就可以使用这种模式。但从库就必须配成启用二进制日志(log_bin, log_slave_updates),还要设成Row格式(binlog_format=ROW),实际上gh-ost会在从库上帮你做这些设置。

事实上,即使把从库改成Row格式,这仍然是对主库侵入最少的工作模式。

模式二、直接在主库上修改

如果没有从库,或者不想在从库上操作,那直接用主库也是可以的。gh-ost就会在主库上直接做所有的操作。仍然可以在上面查看主从复制延迟。

主库必须产生Row格式的二进制日志;

启动gh-ost时必须用--allow-on-master选项来开启这种模式;

模式三、在从库上修改和测试

这种模式会在从库上做修改。gh-ost仍然会连上主库,但所有操作都是在从库上做的,不会对主库产生任何影响。在操作过程中,gh-ost也会不时地暂停,以便从库的数据可以保持最新。

--migrate-on-replica选项让gh-ost直接在从库上修改表。最终的切换过程也是在从库正常复制的状态下完成的。

--test-on-replica表明操作只是为了测试目的。在进行最终的切换操作之前,复制会被停止。原始表和临时表会相互切换,再切换回来,最终相当于原始表没被动过。主从复制暂停的状态下,你可以检查和对比这两张表中的数据。

三种模式各有优缺点,但我只关心缺点:先说模式一的缺点,模式一会在从DB上面读取binlog,可能造成数据库主从数据不一致,原因因为是主库的binlog没有完全在从库执行。所以个人感觉模式一有丢失数据的风险。

模式二任何操作都会在主库操作,或多或少会对主库负载造成影响,但是可以通过调整一些参数降低和时刻关注这些影响,所以个人推荐使用模式二。

至于模式三是偏向测试用的,这里不做过多介绍,但是模式三里有一个细节,cut-over阶段有会stop slave一个操作,其实这个操作风险特别高,有时stop slave 时间会很长,务必会对线上数据库使用造成影响,所以如果使用模式三做测试也要在线下数据库。

gh-ost在GitHub的应用

现在GitHub生产环境的表修改操作全都是用gh-ost完成的。每天只要有需求来了,就将它运行起来,有时候一天会做好多次。因为它有审计和控制功能,所以我们还可以把它和我们的Chatops系统整合起来。技术人员可以对它的工作进度有非常清晰的了解,因此可以控制它的行为。在生产环境中各种指标和事件都被收集起来,让大家可以以图形化的方式看到操作情况。

============  分割线之间内容摘自网络  ============

下面分享gh-ost的测试使用:

1、下载程序

一直都非常喜欢go语言编写的程序,原因很单纯,大部分情况都是一个二进制就能解决问题了,无任何依赖,简直是IT界的一股清流!

解压后就一个 gh-ost 二进制文件,再次献上我坚实的膝盖。

2、常用参数

--max-load

执行过程中,gh-ost会时刻关注负载情况,负载阀值是使用者自己定义,比如数据库的最大连接数,如果超过阀值,gh-ost不会退出,会等待到负载在阀值以下继续执行。

--critical-load

这个指的是gh-ost退出阀值,当负载超过这个阀值,gh-ost会停止并退出

--chunk-size

迁移过程是一步步分批次完成的,这个参数是指事务每次提交的行数,默认是1000。

--max-lag-millis

会监控从库的主从延迟情况,如果延迟秒数超过这个阀值,迁移不会退出,等待延迟秒数低于这个阀值继续迁移。

--throttle-control-replicas

和--max-lag-millis参数相结合,这个参数指定主从延迟的数据库实例。

--switch-to-rbr

当binlog日志格式不是row时,自动转换日志格式

--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文件,重新创建。

--ok-to-drop-table

go-ost执行完以后是否删除老表,加上此参数会自动删除老表。

--host

数据库实例地址。

--port

数据库实例端口。

--user

数据库实例用户名。

--password

数据库实例密码。

--database

数据库名称。

--table

表名。

--verbose

执行过程输出日志。

--alter

操作语句。

--cut-over

自动执行rename操作。

--debug

输出详细日志。

--panic-flag-file

这个文件被创建,迁移操作会被立即终止退出。

--execute

如果确定执行,加上这个参数。

--allow-on-master

整个迁移所有操作在主库上执行,也就是上文介绍的第二种方案:在主库执行。

--throttle-flag-file

此文件存在时操作暂停,删除文件操作会继续。

3、测试过程

本次在单实例DB上执行,采用的连接主库的方案,不能存在任何和主从有关系的参数,比如:

--max-lag-millis

--throttle-control-replicas

--switch-to-rbr

否则会报如下错误:

2018-03-20 15:45:24 FATAL Replication on 192.168.1.1:3306 is broken: Slave_IO_Running: No, Slave_SQL_Running: No. Please make sure replication runs before using gh-ost

最终成功的语句如下:

./gh-ost \

--ok-to-drop-table \

--initially-drop-ghost-table \

--initially-drop-socket-file \

--host="192.168.1.1" \

--port=3306 \

--user="root" \

--password=""\

--database="test_db" \

--table="test_table" \

--verbose \

--alter="add column test_field varchar(256) default '';" \

--panic-flag-file=/tmp/ghost.panic.flag \

--allow-on-master \

--throttle-flag-file /tmp/1.log \

--execute

成功执行过程日志如下:

2018-03-20 15:56:17 INFO starting gh-ost 1.0.44

2018-03-20 15:56:17 INFO Migrating `test_db`.`test_table`

2018-03-20 15:56:17 INFO connection validated on 10.123.104.4:3306

2018-03-20 15:56:17 INFO User has ALL privileges

2018-03-20 15:56:17 INFO binary logs validated on 10.123.104.4:3306

2018-03-20 15:56:17 INFO Restarting replication on 10.123.104.4:3306 to make sure binlog settings apply to replication thread

2018-03-20 15:56:17 INFO Inspector initiated on Tencent64:3306, version 5.5.13-log

2018-03-20 15:56:18 INFO Table found. Engine=InnoDB

2018-03-20 15:56:23 INFO Estimated number of rows via EXPLAIN: 34785

2018-03-20 15:56:23 INFO Recursively searching for replication master

2018-03-20 15:56:23 INFO Master found to be Tencent64:3306

2018-03-20 15:56:23 INFO log_slave_updates validated on 10.123.104.4:3306

2018-03-20 15:56:23 INFO connection validated on 10.123.104.4:3306

2018/03/20 15:56:23 binlogsyncer.go:79: [info] create BinlogSyncer with config {99999 mysql 10.123.104.4 3306 root false false }

2018-03-20 15:56:23 INFO Connecting binlog streamer at mysql-bin.000115:607308817

2018/03/20 15:56:23 binlogsyncer.go:246: [info] begin to sync binlog from position (mysql-bin.000115, 607308817)

2018/03/20 15:56:23 binlogsyncer.go:139: [info] register slave for master server 10.123.104.4:3306

2018/03/20 15:56:23 binlogsyncer.go:573: [info] rotate to (mysql-bin.000115, 607308817)

2018-03-20 15:56:23 INFO rotate to next log name: mysql-bin.000115

2018-03-20 15:56:23 INFO connection validated on 10.123.104.4:3306

2018-03-20 15:56:23 INFO connection validated on 10.123.104.4:3306

2018-03-20 15:56:23 INFO will use time_zone='SYSTEM' on applier

2018-03-20 15:56:23 INFO Examining table structure on applier

2018-03-20 15:56:23 INFO Applier initiated on Tencent64:3306, version 5.5.13-log

2018-03-20 15:56:23 INFO Dropping table `test_db`.`_test_table_gho`

2018-03-20 15:56:23 INFO Table dropped

2018-03-20 15:56:23 INFO Dropping table `test_db`.`_test_table_ghc`

2018-03-20 15:56:23 INFO Table dropped

2018-03-20 15:56:23 INFO Creating changelog table `test_db`.`_test_table_ghc`

2018-03-20 15:56:23 INFO Changelog table created

2018-03-20 15:56:23 INFO Creating ghost table `test_db`.`_test_table_gho`

2018-03-20 15:56:23 INFO Ghost table created

2018-03-20 15:56:23 INFO Altering ghost table `test_db`.`_test_table_gho`

2018-03-20 15:56:23 INFO Ghost table altered

2018-03-20 15:56:23 INFO Intercepted changelog state GhostTableMigrated

2018-03-20 15:56:23 INFO Waiting for ghost table to be migrated. Current lag is 0s

2018-03-20 15:56:23 INFO Handled changelog state GhostTableMigrated

2018-03-20 15:56:23 INFO Chosen shared unique key is PRIMARY

2018-03-20 15:56:23 INFO Shared columns are Id,Version,DeviceTypeId,DeviceClassName,Brand,Status,BoxType,Description,CpuBrand,CpuModel,CpuNumber,CpuSpeed,CpuCore,CpuCache,MemoryVolume,MemoryNumber,MemoryMemo,DiskBrand,DiskModel,DiskSize,DiskMemo,DiskType,DiskVolume,DiskNumber,DiskFirmware,RaidBrand,RaidModel,RaidFirmware,RaidPowerModel,RaidType,RaidShape,RaidTypeId,RaidCache,RaidProtection,RaidNumber,NicBrand,NicSpeed,NicModel,NicFirmware,NicType,PowerSize,PowerNumber,PowerType,BiosVersion,BmcVersion,OutBandInfo,OutBandMemo,SideBandSupport,Height,Width,Depth,Weight,Electricity,Score,MiniOsScore,SsdModel,SsdType,SsdPortType,SsdNumber,SsdFirmware,SsdMemo,GpuModel,GpuNumber,GpuFirmware,GpuMemo,InBandNumber,InBandMemo,PowerMemo,UnselectedParts,PowerCordNumber,PowerCordType,GuideNumber,GuideType,FanNumber,FanModel,StandModel,FanMemo,Memo,GoodsName,GoodsId,MoreGoodsId,ApproveStatus,ApproveType,Editor,DiskBrand2,DiskModel2,DiskSize2,DiskMemo2,DiskType2,DiskVolume2,DiskNumber2,DiskFirmware2,HbaBrand,HbaModel,HbaShape,HbaNumber,HbaFirmware,SsdSize,SsdModel2,SsdType2,SsdPortType2,SsdNumber2,SsdFirmware2,SsdMemo2,SsdSize2,reason,ChildCount,BiosType

2018-03-20 15:56:23 INFO Listening on unix socket file: /tmp/gh-ost.test_db.test_table.sock

2018-03-20 15:56:23 INFO Migration min values: [1]

2018-03-20 15:56:23 INFO Migration max values: [112678]

2018-03-20 15:56:23 INFO Waiting for first throttle metrics to be collected

2018-03-20 15:56:23 INFO First throttle metrics collected

# Migrating `test_db`.`test_table`; Ghost table is `test_db`.`_test_table_gho`

# Migrating Tencent64:3306; inspecting Tencent64:3306; executing on Tencent64

# Migration started at Tue Mar 20 15:56:17 +0800 2018

# chunk-size: 1000; max-lag-millis: 1500ms; dml-batch-size: 10; max-load: ; critical-load: ; nice-ratio: 0.000000

# throttle-flag-file: /tmp/1.log

# throttle-additional-flag-file: /tmp/gh-ost.throttle

# panic-flag-file: /tmp/ghost.panic.flag

# Serving on unix socket: /tmp/gh-ost.test_db.test_table.sock

Copy: 0/34785 0.0%; Applied: 0; Backlog: 0/1000; Time: 5s(total), 0s(copy); streamer: mysql-bin.000115:607310620; State: migrating; ETA: N/A

Copy: 0/34785 0.0%; Applied: 0; Backlog: 0/1000; Time: 6s(total), 1s(copy); streamer: mysql-bin.000115:607314289; State: migrating; ETA: N/A

Copy: 6000/34785 17.2%; Applied: 0; Backlog: 0/1000; Time: 7s(total), 2s(copy); streamer: mysql-bin.000115:614577193; State: migrating; ETA: 9s

Copy: 12000/34785 34.5%; Applied: 0; Backlog: 0/1000; Time: 8s(total), 3s(copy); streamer: mysql-bin.000115:625222709; State: migrating; ETA: 5s

Copy: 18000/34785 51.7%; Applied: 0; Backlog: 0/1000; Time: 9s(total), 4s(copy); streamer: mysql-bin.000115:635491410; State: migrating; ETA: 3s

Copy: 24000/34785 69.0%; Applied: 0; Backlog: 0/1000; Time: 10s(total), 5s(copy); streamer: mysql-bin.000115:642674598; State: migrating; ETA: 2s

Copy: 31000/34785 89.1%; Applied: 0; Backlog: 0/1000; Time: 11s(total), 6s(copy); streamer: mysql-bin.000115:650916749; State: migrating; ETA: 0s

2018-03-20 15:56:29 INFO Row copy complete

Copy: 34199/34199 100.0%; Applied: 0; Backlog: 0/1000; Time: 11s(total), 6s(copy); streamer: mysql-bin.000115:656445063; State: migrating; ETA: due

2018-03-20 15:56:29 INFO Grabbing voluntary lock: gh-ost.55507235.lock

2018-03-20 15:56:29 INFO Setting LOCK timeout as 6 seconds

2018-03-20 15:56:29 INFO Looking for magic cut-over table

2018-03-20 15:56:29 INFO Creating magic cut-over table `test_db`.`_test_table_del`

2018-03-20 15:56:30 INFO Magic cut-over table created

2018-03-20 15:56:30 INFO Locking `test_db`.`test_table`, `test_db`.`_test_table_del`

2018-03-20 15:56:30 INFO Tables locked

2018-03-20 15:56:30 INFO Session locking original & magic tables is 55507235

2018-03-20 15:56:30 INFO Writing changelog state: AllEventsUpToLockProcessed:1521532590048817923

2018-03-20 15:56:30 INFO Intercepted changelog state AllEventsUpToLockProcessed

2018-03-20 15:56:30 INFO Handled changelog state AllEventsUpToLockProcessed

2018-03-20 15:56:30 INFO Waiting for events up to lock

Copy: 34199/34199 100.0%; Applied: 0; Backlog: 1/1000; Time: 12s(total), 6s(copy); streamer: mysql-bin.000115:656447931; State: migrating; ETA: due

2018-03-20 15:56:30 INFO Waiting for events up to lock: got AllEventsUpToLockProcessed:1521532590048817923

2018-03-20 15:56:30 INFO Done waiting for events up to lock; duration=919.561495ms

# Migrating `test_db`.`test_table`; Ghost table is `test_db`.`_test_table_gho`

# Migrating Tencent64:3306; inspecting Tencent64:3306; executing on Tencent64

# Migration started at Tue Mar 20 15:56:17 +0800 2018

# chunk-size: 1000; max-lag-millis: 1500ms; dml-batch-size: 10; max-load: ; critical-load: ; nice-ratio: 0.000000

# throttle-flag-file: /tmp/1.log

# throttle-additional-flag-file: /tmp/gh-ost.throttle

# panic-flag-file: /tmp/ghost.panic.flag

# Serving on unix socket: /tmp/gh-ost.test_db.test_table.sock

Copy: 34199/34199 100.0%; Applied: 0; Backlog: 0/1000; Time: 12s(total), 6s(copy); streamer: mysql-bin.000115:656449972; State: migrating; ETA: due

2018-03-20 15:56:30 INFO Setting RENAME timeout as 3 seconds

2018-03-20 15:56:30 INFO Session renaming tables is 55507237

2018-03-20 15:56:30 INFO Issuing and expecting this to block: rename /* gh-ost */ table `test_db`.`test_table` to `test_db`.`_test_table_del`, `test_db`.`_test_table_gho` to `test_db`.`test_table`

2018-03-20 15:56:30 INFO Found atomic RENAME to be blocking, as expected. Double checking the lock is still in place (though I don't strictly have to)

2018-03-20 15:56:30 INFO Checking session lock: gh-ost.55507235.lock

2018-03-20 15:56:30 INFO Connection holding lock on original table still exists

2018-03-20 15:56:30 INFO Will now proceed to drop magic table and unlock tables

2018-03-20 15:56:30 INFO Dropping magic cut-over table

2018-03-20 15:56:30 INFO Releasing lock from `test_db`.`test_table`, `test_db`.`_test_table_del`

2018-03-20 15:56:30 INFO Tables unlocked

2018-03-20 15:56:31 INFO Tables renamed

2018-03-20 15:56:31 INFO Lock & rename duration: 951.985633ms. During this time, queries on `test_table` were blocked

2018-03-20 15:56:31 INFO Looking for magic cut-over table

2018/03/20 15:56:31 binlogsyncer.go:107: [info] syncer is closing...

2018/03/20 15:56:31 binlogstreamer.go:47: [error] close sync with err: sync is been closing...

2018/03/20 15:56:31 binlogsyncer.go:122: [info] syncer is closed

2018-03-20 15:56:31 INFO Closed streamer connection. err=

2018-03-20 15:56:31 INFO Dropping table `test_db`.`_test_table_ghc`

2018-03-20 15:56:31 INFO Table dropped

2018-03-20 15:56:31 INFO Dropping table `test_db`.`_test_table_del`

2018-03-20 15:56:31 INFO Table dropped

2018-03-20 15:56:31 INFO Done migrating `test_db`.`test_table`

2018-03-20 15:56:31 INFO Removing socket file: /tmp/gh-ost.test_db.test_table.sock

2018-03-20 15:56:31 INFO Tearing down inspector

2018-03-20 15:56:31 INFO Tearing down applier

2018-03-20 15:56:31 INFO Tearing down streamer

2018-03-20 15:56:31 INFO Tearing down throttler

# Done

执行完成后,查看表结构,已经创建成功了。

使用过程中遇到的问题记录:

问题1、对于主从结构DB集群,Binlog日志格式必须是ROW模式,否则会有如下报错:

2018-03-20 19:51:08 FATAL 192.168.1.1:3306 has MIXED binlog_format, but I'm too scared to change it to ROW because it has replicas. Bailing out

解决办法:

执行gh-ost之前,先将binlog格式动态改为ROW模式(不会影响主从同步):

SET GLOBAL binlog_format = 'ROW';

然后,再执行gh-ost就可以了,如果后面需要MIXED模式,可以再次动态修改回来即可。

问题2、修改对象表不能被触发器关联,gh-ost虽然不再依赖触发器,但是依然不支持有触发器关联的表,如果修改有触发器关联的表,则会有如下提示:

2018-03-21 08:22:48 ERROR Found triggers on `ndb`.`net_device_parts`. Triggers are not supported at this time. Bailing out

问题3、修改对象表不能被外键关联,否则如下报错:

2018-03-21 08:20:21 FATAL 2018-03-21 08:20:21 ERROR Found 7 parent-side foreign keys on `ndb`.`net_device`. Parent-side foreign keys are not supported. Bailing out

问题4、FATAL Unexpected database port reported

该问题主要发生在主主模式,且使用自定义端口的情况,解决办法:在-assume-master-host参数后面添加主机的端口号,比如:-assume-master-host=192.168.1.1:3307

已根据生产环境实际使用,分享了一篇简单的经验总结,欢迎感兴趣的同学可以继续查阅。

mysql gh 划线,gh-ost:在线DDL修改MySQL表结构工具相关推荐

  1. mysql+不锁表添加字段_MySQL5.6在线DDL不锁表(在线添加字段)

    解答你也看一下 MySQL5.6在线DDL不锁表,现在我有一张1亿的表,需要增加一个字段,假如我让你去增加这个字段,你应该注意什么,具体怎么操作? 操作如下: 1.注意磁盘空间(临时表目录 参数 tm ...

  2. gh ost mysql_mysql 在线修改表结构工具 gh-ost

    -allow-master-master 显式的允许在主主集群中运行-allow-on-master 允许直接运行在主机上,如果没有集群使用这个选项,推荐用在从机上-alter string(必须参数 ...

  3. mysql更改密码的sql语句_修改mysql登录密码与sql语句介绍

    修改mysql登录密码: 在使用数据库服务器过程中可能会因为种种原因忘记了登录密码,或者需要使用别人的数据库服务器,别人却忘记了登录密码等等. 忘记密码有两种方式可以解决,一是通过sql语句修改登录密 ...

  4. 如何在linux系统下修改mysql密码_如何在linux下修改mysql数据库密码?linux修改数据库密码的方法...

    本篇文章给大家带来的内容是介绍如何在linux下修改mysql数据库密码?linux修改数据库密码的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助. Linux下修改Mysql的 ...

  5. 修改mysql数据库名方法_安全快速修改Mysql数据库名的5种方法

    1. RENAME DATABASE db_name TO new_db_name 这个..这个语法在mysql 5.1.7中被添加进来,到了5.1.23又去掉了. 据说有可能丢失数据.还是不要用的好 ...

  6. mysql root密码忘记2018_2018-03-28设置及修改mysql用户密码学习笔记

    退出mysql方法 quit或者exit 设置及修改mysqlroot用户密码 安装mysql后,默认管理员root密码为空,这很不安全,需要设置一个密码,在安装mysql单实例后,有个初始优化的一些 ...

  7. mysql数据库改成支持中文_修改Mysql编码支持中文

    MySQL的默认编码是Latin1,不支持中文,要支持中午需要把数据库的默认编码修改为gbk或者utf8. 1.需要以root用户身份登陆才可以查看数据库编码方式(以root用户身份登陆的命令为:&g ...

  8. 阿里云服务器mysql默认密码_阿里云服务器修改MySQL初始密码---Linux学习笔记

    主要方法就是修改 MySQL按照文件下面的my.cnf文件 首先是找到my.cnf文件, # find / -name "my.cnf" # cd /etc 接下来最好是先备份my ...

  9. 织梦数据库改mysql前缀_织梦快速批量修改MYSQL数据库表前缀与表名实例操作

    这篇文章主要为大家详细介绍了织梦快速批量修改MYSQL数据库表前缀与表名实例操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,有需要的朋友可以收藏方便以后借鉴. 我们在安装织梦系统的时候,有一次 ...

最新文章

  1. 思维 ---- 两两匹配问题 2021杭电多校第6场 E - Median
  2. 第十二周项目一-实现复数类中的运算符重载(2)
  3. 边缘计算架构_多接入边缘计算框架与参考架构简介
  4. webRTC——浏览器里的音视频通话
  5. MVC路由学习:自定义路由参数(用户看不到参数名),重新定义路由规则
  6. el-table合并行的实现
  7. seaborn.heatmap概述
  8. 推荐系统--联邦学习下的矩阵分解(6)
  9. javascript闭包原理
  10. 使用Fsharp 探索 Dotnet 平台
  11. 用Keras搭建神经网络 简单模版(三)—— CNN 卷积神经网络(手写数字图片识别)...
  12. jq cookie的使用
  13. 【解决】小程序要求的 TLS 版本必须大于等于 1.2
  14. HDU ACM 3986 Harry Potter and the Final Battle(邻接表实现最短路dijkstra堆优化记录路径 + 枚举最短路上每条边)...
  15. 一点创业想法:读书类垂直博客
  16. 同济大学高等数学第7版笔记和课后答案
  17. JS 正则表达式 数字和小数点 非负数 保留两位小数点
  18. JVM(3)-垃圾收集机制
  19. 卷积神经网络CNN简图
  20. c语言 运行结果是空白的,为什么输出是空白

热门文章

  1. win10matlab2016启动卡,教你解决win10专业版开机卡死的方法
  2. 新东方java开发面试经历---现场面试(2021年1月)
  3. 推荐|45个值得收藏的Python优质资源(附链接)
  4. 实验一 词法分析程序设计与实现 (Java实现)
  5. html怎么实现展开,HTML使用DIV+css实现展开全文的功能
  6. android 手机输入法表情,最近手机输入法玩出花,讯飞输入法安卓版让表情包说话?...
  7. python format输入你的身高和体重,输出你的BMI值,以及你的胖瘦情况
  8. 张铁柱-前端实现《低代码可视化编辑器》(一)思路整理 React-dnd+Ts
  9. 自学IOS开发第3天·基础SwiftUI之动态滑动列表(上)
  10. Winodws 7 专业番茄花园版 v 1.0