说一下最后一个SQL,接下来要开始跟着commit来进一步理解了。
DROP TABLE t;
入口和之前语句一样,也是个Exec类型的语句。
直接进入Exec():
// Exec implements the stmt.Statement Exec interface. func (s *DropTableStmt) Exec(ctx context.Context) (rset.Recordset, error) { var notExistTables []string for _, ti := range s.TableIdents { err := sessionctx.GetDomain(ctx).DDL().DropTable(ctx, ti.Full(ctx)) if err != nil && strings.HasSuffix(err.Error(), "not exist") { notExistTables = append(notExistTables, ti.String()) } else if err != nil { return nil, errors.Trace(err) } } if len(notExistTables) > 0 && !s.IfExists { return nil, errors.Errorf("DROP TABLE: table %s does not exist", strings.Join(notExistTables, ",")) } return nil, nil }
err := sessionctx.GetDomain(ctx).DDL().DropTable(ctx, ti.Full(ctx))这里获得ddl后进入DropTable:
// drop table will proceed even if some table in the list does not exists func (d *ddl) DropTable(ctx context.Context, ti table.Ident) (err error) { is := d.GetInformationSchema() tb, err := is.TableByName(ti.Schema, ti.Name) if err != nil { return errors.Trace(err) } // update InfoSchema before delete all the table data. clonedInfo := is.Clone() for _, info := range clonedInfo { if info.Name == ti.Schema { var newTableInfos []*model.TableInfo // append other tables. for _, tbInfo := range info.Tables { if tbInfo.Name.L != ti.Name.L { newTableInfos = append(newTableInfos, tbInfo) } } info.Tables = newTableInfos err = d.writeSchemaInfo(info) if err != nil { return errors.Trace(err) } } } d.infoHandle.Set(clonedInfo) err = d.deleteTableData(ctx, tb) return errors.Trace(err) }
https://github.com/pingcap/tidb/blob/0d6f270068e8ff2aedc1c314e907771b6a508ebd/ddl/ddl.go#L406-L434
这里先把表删除后的InfoSchema更新,然后再进入d.deleteTableData(ctx, tb)删除表中的数据:
func (d *ddl) deleteTableData(ctx context.Context, t table.Table) error { // Remove data err := t.Truncate(ctx) if err != nil { return errors.Trace(err) } txn, err := ctx.GetTxn(false) if err != nil { return errors.Trace(err) } // Remove indices for _, v := range t.Indices() { if v != nil && v.X != nil { if err = v.X.Drop(txn); err != nil { return errors.Trace(err) } } }
https://github.com/pingcap/tidb/blob/0d6f270068e8ff2aedc1c314e907771b6a508ebd/ddl/ddl.go#L436-L453
这里err := t.Truncate(ctx)删除所有数据行,根据表前缀即可扫描出所有该表的数据。
t.Indices()把所有索引对应的所有数据行删除。
接下来:
// Remove auto ID key err = txn.Delete([]byte(meta.AutoIDKey(t.TableID()))) // Auto ID meta is created when the first time used, so it may not exist. if errors2.ErrorEqual(err, kv.ErrNotExist) { return nil } return errors.Trace(err) }
https://github.com/pingcap/tidb/blob/0d6f270068e8ff2aedc1c314e907771b6a508ebd/ddl/ddl.go#L454-L462
这里删除了行号/autoID。
到此,这个SQL完成了。
小结
是一个比较简单的SQL,流程:验证合法性->删除表中数据行->删除所有索引->删除标记行号的变量(autoID).