研发同学问,gh-ost做DDL时,业务可对原表做DML,同时一边apply binlog event,一边rowcopy到新表,那么问题来了,这仨操作存在先后顺序,不按顺序会产生数据不一致吗?
既然是说gh-ost,那么先放个图镇楼。

继续说正文)首先,举个栗子:
id | balance
--------------
1 | 100
变更过程中,因为不阻塞
DML,业务先对原始表
+100
(同时产生了该
UPDATE的
binlog event)
:
id | balance
--------------
1 | 200
这行再被
INSERT到新表,此时
id=1的
balance已经是
200。
最后解析
binlog apply到新表时,将
UPDATE语句再次
apply,
balance会变为
300吗?
所以,不一样的顺序是否会造成数据不一致?
DDL更变的过程中,涉及三种操作:
A、rowcopy(即数据copy到新表)
B、正常新增的DML(指对原表执行DML)
C、binlog apply到新表(指分析binlog
event后应用到新表)
首先明确一点,
C一定要在
B之后,先生成了
binlog event,才会有对新表的
apply
所以更变时可能出现三种组合,如下:
1)A->B->C,原始数据先被copy到新表,原表产生binlog,再解析binlog去对新表做apply。
2)B->C->A,主库产生binlog,再应用binlog,copyrow到新表。
3)B->A->C,主库产生binlog,copyrow到新表,再应用binlog。
首先想一下
gh-ost的对表的两个核心限制:
1)必须有PK(或不存在
NULL的UK),可以精准定位到某一行。
2)binlog_format=ROW,可以拿到整行数据。
有了这两个前提,
gh-ost会认为
binlog events的数据是最准的,于是讨论一致性,就简单了:
分析一下rowcopy和DML的实现
rowcopy):
纯
INSERT操作,其实就对原表做
SELECT,对新表
INSERT INTO IGNORE
对于原始
binlog events,
binlog apply时的几个改写):
对于
INSERT的DML,
apply时改为
REPLACE
INTO
对于
DELETE的DML,还是
DELETE
对于
UPDATE的DML,更新完整一行
INSERT):
如果apply先,rowcopy后:
比如对于PK=1的,自然以binlog为准,rowcopy遇到PK=1,IGNORE了
如果rowcopy先,apply后:
比如对于PK=1的,
REPLACE
INTO掉,依然以
binlog为准,盖掉整行
所以rowcopy和
binlog
events相遇,
binlog为准。
DELETE):
1)A->B->C,这种组合始终不影响,先前rowcopy的数据在整个过程中产生了B和
C,删掉了这一行很正常。
2)B->C->A,BC先做,数据删掉了,A再rowcopy,这个时候对原表执行
SELECT,等于没读到数据,什么都没查到,没所谓。
3)B->A->C,B先产生DELETE语句,A再rowcopy,对原表执行SELECT,什么数
据没读到,依然没所谓。C在做apply的时候等于没做。
UPDATE):
1)A->B->C,A先rowcopy,B再生成binlog更新,最后apply,因为binlog记录整行数据,
所以也更新整行数据就好,不会出现重复更新的情况。
2)B->C->A,BC先做,因为A还没做,实际上执行C的时候,新表是找不到PK=
1
这行数据的,更新了个空气,此时再做A,就等于把整行INSERT进来了,安全。
3)B->A->C,B先产生一条UPDATE,A做rowcopy的时候,INSERT的是最新的数
据,最后C做apply的时候,以binlog为准,因为还是更新整行数据,所以依然也不会出现重复更新的情况。
有没有一点像
Redis
的
AOF
,无论中间出现什么,重写时就以最后一条为准。 唯一的
KEY
对应唯一的
VALUE
,无论整个过程中发生了些什么。
btw
,隔壁
pt-osc也是有类似的
SQL改写逻辑。
所以可以一边
copy原始数据到新表,一边用触发器捕获对原表的变更,并写到新表。
再康康cut-over
cut-over简单理解为就是最后原表和新表做交换的整个过程。或者叫切换。
简单来说,
gh-ost用两个连接(以下用A和B替代)做了一些事,按时间顺序如下:
A)、
CREATE
TABLE tbl_old (
id
int primary
key)
COMMENT=
'magic-be-here'
然后
LOCK
TABLES tbl WRITE, tbl_old WRITE
B)、
RENAME
TABLE tbl
TO tbl_old, ghost
TO tbl。
这个时候B会话会hang着。
A)、检查B的被blocked的
RENAME(通过
SHOW
PROCESSLIST),
继续做
DROP
TABLE tbl_old,
UNLOCK
TABLES;,
整个过程,依然是有很多其他会话尝试进行DML操作的。
那么这套流程是如何保证原子性的呢?
看看任何一步失败的影响:
1)如果A做
CREATE tbl_old时挂,没所谓,不影响业务。
2)如果A做
LOCK
TABLE tbl/tbl_old时挂了,不影响业务。
3)如果A在
CREATE和
LOCK都成功后,连接断开,不影响业务:
①,此时B还没执行:A断开,写锁释放,准备做
RENAME时,会报表tbl_old存在。
②,此时B等待执行(被hang住):A断开,写锁释放,终于可以
RENAME了,
还是会报表tbl_old存在。
-- 所以,tbl_old这个空表的作用就出来了。
4)如果B在
RENAME前(也就是hang住时)挂了,gh-ost会捕获这个错误,
并且继续按原计划执行
DROP和
UNLOCK,这样也不影响业务
5)如果B在A做
DROP
TABLE时挂了,A一样会按原计划执行
DROP和
UNLOCK,依旧不影响业务。
总之,上面的任何一步出现问题,
gh-ost都会检查下新表在不在,如果不在了,说明已经成功了。如果还在,那就说明最后的
cut-over过程失败了。
对了,如果
LOCK TABLE时加不上,也可以控制加锁等待时长的,默认应该是
3s,参考(由
cut-over-lock-timeout-seconds控制),重试次数由
default-retries控制,默认
60次。
整个过程可以大概如下:
会话A创
tbl_old表和对原表、
tbl_old加锁,当然也有可能加不上锁,因为可能之前的会话还未提交等
对该表的新读写请求被阻塞
会话B执行
RENAME,被阻塞
对该表的新增的读写请求继续被阻塞
会话A检查是否有被阻塞的
RENAME
会话A删除
tbl_old和释放写锁
会话B RENAME成功
所有被阻塞的读写请求于新表
我是个憨憨,看到这个过程想吐槽,
锁表操作是不是多此一举?
该项目
issues也有老哥问了这个问题:
Shawn001 commented on 25 Apr
hello
why can't
use
rename t1
to t1_del, t1_gho
to t1 directly,
are there
some problems?
其实是为了避免产生新的
binlog event,如果不锁,其他会话可能会继续做
DML。
附录:
1)RENAME TABLE还是相对安全的,MySQL手册里也有描述: If any errors occur during a RENAME TABLE, the statement fails and no changes are made.
2)UNLOCK TABLES后,被hang住的DML比RENAME插队执行怎么办?
这个问题
gh-ost开发者就是一句话告诉大家:
A blocked RENAME is always prioritized over a blocked INSERT/UPDATE/DELETE, no matter who came first。大概意思就是无论
DML还是
RENAME先到,
RENAME总是第一个先跑的,这样就可以保证不会产生新的
binlog events。
至于原因,google了一下,理由在这里 https://github.com/mysql/mysql-server/blob/a533e2c786164af9bd276660b972d93649434297/sql/mdl.cc#L2312
cut-over参考如下
https://github.com/github/gh-ost/issues/82
https://github.com/github/gh-ost/blob/master/doc/cut-over.md

编辑推荐:
- gh-ost核心原理:数据一致性和cut-over03-01
- 14.2 InnoDB 和 ACID 模型03-01
- CPU占用又爆了?MySQL到底在干什么03-01
- 利用binlog日志恢复mysql数据03-01
- mysql基础知识03-01
- 优秀数据库管理工具比较,CloudQuery赢了!03-01
- 比MySQL快839倍!揭开分析型数据库JCHDB的神秘面纱 京东智联云开发者03-01
- Linux上安装Mysql03-01
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
