在运维dble集群的过程中,有时会遇到 " There is other session is doing DDL " 或者 "xxx is doing DDL " 等问题,这些问题会导致某些表无法被操作,无法进行 reload 等。此时,需要人工干预保证集群运行正常。
在 dble 集群中,可以通过 ZK 中某些键值对推断正在执行 DDL 的节点状态,比如通过键 universe/dble/{cluster-id}/ddl/{schema.table} 的值内容推断。该值理论上只会被发起者节点所修改,其他节点会订阅该键值,该值的内容为json格式,其中有一个 status 字段:
-
status 为 INIT 时,发起动作的节点会锁住本节点对应 table 的 table meta并获取当前key的分布式锁。其他的dble节点订阅到该值后会锁住本节点上对应 table 的 table meta;
-
待发起节点执行DDL之后,会根据 DDL 执行结果更新当前键的值,此时根据 DDL 执行结果 status 分为两种情形:SUCCESS 和 FAILED。其他节点订阅到 status 为 SUCCESS 时,才会真正执行对应的DDL操作,否则会取消执行DDL并释放本节点对应table 的 table meta 锁;
-
每个节点都会插入一条 universe/dble/{cluster-id}/ddl/{schema.table}/{dble-id}:SUCCESS 数据。
到此,除发起者的节点执行已经结束,但是发起者节点会等待其他节点响应,只有全部节点都汇报执行完成之后,当前ddl才算完成。
发起者节点通过什么来判断其他节点都响应完成?根据以下两个键的内容:
-
universe/dble/{cluster-id}/ddl/{schema.table}/{dble-id}
-
universe/dble/{cluster-id}/online/下属结点
所有执行当前DDL操作的节点都会在universe/dble/{cluster-id}/ddl/{schema.table}/ 下面插入记录,发起节点通过判断 online 节点是否在 universe/dble/{cluster-id}/ddl/{schema.table}/ 下面留下记录判断 DDL 是否被该节点所应用。只有两者相符合时,ddl才算真正意义上的完成。
此时,发起者会释放 table meta 锁 和 分布式锁,并且删除 universe/dble/{cluster-id}/ddl/{schema.table}
kv 树。
当前指令只会释放对应ddl在当前节点中所持有的元数据锁,但是不会影响执行该ddl的线程的状态。 若出现上述问题,可以参考 上面如何判断其他节点都响应完成的方式找出哪些没有响应,在这些节点和发起节点上执行当前命令,并手动删除universe/dble/{cluster-id}/ddl/{schema.table} kv 树。
- 需要注意kill指令的执行顺序:先在各个从节点上执行该指令,最后再在主节点上执行。
- 如果不是特殊因素,此命令请不要随意使用。