TIDB源码分析-从github第一次提交说起(6)

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

https://github.com/pingcap/tidb/blob/0d6f270068e8ff2aedc1c314e907771b6a508ebd/stmt/stmts/drop.go#L105-L120

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).

发表评论

电子邮件地址不会被公开。 必填项已用*标注

请输入正确的验证码