diff --git a/executor/ddl.go b/executor/ddl.go index ced59b52fb302..0f19c49d1a98b 100644 --- a/executor/ddl.go +++ b/executor/ddl.go @@ -156,6 +156,13 @@ func (e *DDLExec) executeCreateIndex(s *ast.CreateIndexStmt) error { func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error { dbName := model.NewCIStr(s.Name) + + // Protect important system table from been dropped by a mistake. + // I can hardly find a case that a user really need to do this. + if dbName.L == "mysql" { + return errors.New("Drop 'mysql' database is forbidden") + } + err := domain.GetDomain(e.ctx).DDL().DropSchema(e.ctx, dbName) if infoschema.ErrDatabaseNotExists.Equal(err) { if s.IfExists { @@ -179,6 +186,24 @@ func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error { return errors.Trace(err) } +// If one drop those tables by mistake, it's difficult to recover. +// In the worst case, the whole TiDB cluster fails to bootstrap, so we prevent user from dropping them. +var systemTables = map[string]struct{}{ + "tidb": {}, + "gc_delete_range": {}, + "gc_delete_range_done": {}, +} + +func isSystemTable(schema, table string) bool { + if schema != "mysql" { + return false + } + if _, ok := systemTables[table]; ok { + return true + } + return false +} + func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error { var notExistTables []string for _, tn := range s.Tables { @@ -198,6 +223,12 @@ func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error { return errors.Trace(err) } + // Protect important system table from been dropped by a mistake. + // I can hardly find a case that a user really need to do this. + if isSystemTable(tn.Schema.L, tn.Name.L) { + return errors.Errorf("Drop tidb system table '%s.%s' is forbidden", tn.Schema.L, tn.Name.L) + } + if config.CheckTableBeforeDrop { log.Warnf("admin check table `%s`.`%s` before drop.", fullti.Schema.O, fullti.Name.O) sql := fmt.Sprintf("admin check table `%s`.`%s`", fullti.Schema.O, fullti.Name.O) diff --git a/executor/ddl_test.go b/executor/ddl_test.go index 87c69c5b95ac2..4d102ffa0cc20 100644 --- a/executor/ddl_test.go +++ b/executor/ddl_test.go @@ -128,6 +128,9 @@ func (s *testSuite) TestCreateDropDatabase(c *C) { c.Assert(err.Error(), Equals, plan.ErrNoDB.Error()) _, err = tk.Exec("select * from t;") c.Assert(err.Error(), Equals, plan.ErrNoDB.Error()) + + _, err = tk.Exec("drop database mysql") + c.Assert(err, NotNil) } func (s *testSuite) TestCreateDropTable(c *C) { @@ -137,6 +140,9 @@ func (s *testSuite) TestCreateDropTable(c *C) { tk.MustExec("drop table if exists drop_test") tk.MustExec("create table drop_test (a int)") tk.MustExec("drop table drop_test") + + _, err := tk.Exec("drop table mysql.gc_delete_range") + c.Assert(err, NotNil) } func (s *testSuite) TestCreateDropIndex(c *C) {