说一下最后一个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).