整个 DDL 的执行流程大致是这样(具体的原理可以参考 【SOP 系列 03】在线表结构变更(Online DDL)):
第一步,TiDB 收到 SQL 请求,转化成 DDL Job 发出去
第二步,Owner 节点收到 Job 开始分发处理该 Job
第三步,Woker 节点收到 Job,开始执行,并更新进度
第四步,DDL 完成
在排查 DDL 卡住的问题时,我们需要确定 DDL 是在哪一步卡住的。
执行 admin show ddl jobs 如果能看到 DDL 的信息,说明第一步已经完成。
DDL 卡住的问题大多数都是卡在第二步或者第三步。接着我们需要排查是否卡在第二步,也就是确认 DDL owner 是否正常。 执行 curl http://{TiDBIP}:{TiDBPORT}/info/all 可以看到集群的所有 TiDB 节点,上面步骤可以确认有没有 Owner 存在。
如果 Owner 不存在,可能是 TiDB 刚刚 Panic 过, 没有释放在 PD 上面的注册信息,需要等待 lease 过期(默认 45s)才能重新选出 Owner。 如果 Owner 存在,需要检查 Owner 是否在正常地工作。 可以尝试以下两种方法:
- 抓取 Owner 当前的 Goroutine 栈,看卡在哪个函数中。
- 检查 Owner 节点的日志,看是否有报错信息。
如果确认过整个流程是在往前推进,这个时候应该不是卡住,只是执行一些步骤慢。 大表加索引慢可能是正常的,因为工作量大。 有些有依赖的 Jobs 前面 block 后面也是正常的。 还可能是 load schema 慢,拿 auto id 慢,等等。
其他: 可以踢掉 Owner,尝试重新选取 Owner,这在遇到 Panic 的旧的 Owner 时比较有用。
1.找到 owner :curl -X POST http://{TiDBIP}:10080/ddl/owner/resign
2.旁路下线:tidb-ctl etcd delkey [LeaseID] [flags] ownerKey