Skip to content

DDL同步

lydarkforest edited this page Jun 21, 2019 · 5 revisions

从v1.5版本开始,MongoShake已经支持了DDL的同步,用户可以通过配置文件中的replayer.dml_only控制是否同步DDL。DDL语句包括:建库、建表、删库、删表、建索引、4.0事务等,如果replayer.dml_only=true表示不同步这些语句,只同步DML语句,false则为启用。

实现原理

如果没有启用DDL的参数,那么MongoShake是按表进行并发的,表内还会再进行写入的并发,这样的话无法控制同步的因果一致性,比如insert a; drop database;这两个操作如果进行并发,那么并发的顺序直接影响了同步的结果。所以对这些语句的顺序需要进行控制,MongoShake的做法是采用全局barrier的机制:发现DDL语句,将会卡2次barrier,1次是保证DDL之前的语句都已经同步完毕,1次是保证本条DDL语句同步完毕,如下图所示: DDL.png
同时每次barrier结束都将会触发checkpoint的更新,保证DDL语句不会因为挂掉被重传。但此处也会有另外一个小概率的问题,假设DDL语句已经同步完毕了,但此时checkpoint还没来得及更新,MongoShake就挂了,然后重启后这条语句被重传报错。这就需要运维介入进行解决,比如把checkpoint往后推一条(可以在日志中拿到这条DDL的时间戳,然后更新checkpoint),或者在目的端删除DDL带来的操作(比如DDL是建库,则变成删库)。

限制

如果用户选择全量+增量同步(sync_mode=all),那么在全量开始的时候我们会记录一个oplog的位点a,在全量结束的时候我们会记录另一个oplog的位点b。然后全量结束,增量的位点将会从a开始拉取,那么这就要求在[a, b]这段时间内不能有DDL操作,b之后的位点不影响。

注意

因为MongoDb不同版本的ddl的oplog格式可能不一样,所以支持ddl种类可能不全,所以对于不支持的ddl不会被同步。用户如果在MongoShake日志中发现extraCommandName meets type ... which is not implemented的日志,请告知我们,我们会考虑做支持