Skip to content

Commit 55af7e1

Browse files
tiancaiamaojackysp
authored andcommitted
executor: forbid user to drop important system table (pingcap#7471)
1 parent 69d5e36 commit 55af7e1

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

executor/ddl.go

+31
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ func (e *DDLExec) executeCreateIndex(s *ast.CreateIndexStmt) error {
156156

157157
func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error {
158158
dbName := model.NewCIStr(s.Name)
159+
160+
// Protect important system table from been dropped by a mistake.
161+
// I can hardly find a case that a user really need to do this.
162+
if dbName.L == "mysql" {
163+
return errors.New("Drop 'mysql' database is forbidden")
164+
}
165+
159166
err := domain.GetDomain(e.ctx).DDL().DropSchema(e.ctx, dbName)
160167
if infoschema.ErrDatabaseNotExists.Equal(err) {
161168
if s.IfExists {
@@ -179,6 +186,24 @@ func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error {
179186
return errors.Trace(err)
180187
}
181188

189+
// If one drop those tables by mistake, it's difficult to recover.
190+
// In the worst case, the whole TiDB cluster fails to bootstrap, so we prevent user from dropping them.
191+
var systemTables = map[string]struct{}{
192+
"tidb": {},
193+
"gc_delete_range": {},
194+
"gc_delete_range_done": {},
195+
}
196+
197+
func isSystemTable(schema, table string) bool {
198+
if schema != "mysql" {
199+
return false
200+
}
201+
if _, ok := systemTables[table]; ok {
202+
return true
203+
}
204+
return false
205+
}
206+
182207
func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
183208
var notExistTables []string
184209
for _, tn := range s.Tables {
@@ -198,6 +223,12 @@ func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
198223
return errors.Trace(err)
199224
}
200225

226+
// Protect important system table from been dropped by a mistake.
227+
// I can hardly find a case that a user really need to do this.
228+
if isSystemTable(tn.Schema.L, tn.Name.L) {
229+
return errors.Errorf("Drop tidb system table '%s.%s' is forbidden", tn.Schema.L, tn.Name.L)
230+
}
231+
201232
if config.CheckTableBeforeDrop {
202233
log.Warnf("admin check table `%s`.`%s` before drop.", fullti.Schema.O, fullti.Name.O)
203234
sql := fmt.Sprintf("admin check table `%s`.`%s`", fullti.Schema.O, fullti.Name.O)

executor/ddl_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ func (s *testSuite) TestCreateDropDatabase(c *C) {
128128
c.Assert(err.Error(), Equals, plan.ErrNoDB.Error())
129129
_, err = tk.Exec("select * from t;")
130130
c.Assert(err.Error(), Equals, plan.ErrNoDB.Error())
131+
132+
_, err = tk.Exec("drop database mysql")
133+
c.Assert(err, NotNil)
131134
}
132135

133136
func (s *testSuite) TestCreateDropTable(c *C) {
@@ -137,6 +140,9 @@ func (s *testSuite) TestCreateDropTable(c *C) {
137140
tk.MustExec("drop table if exists drop_test")
138141
tk.MustExec("create table drop_test (a int)")
139142
tk.MustExec("drop table drop_test")
143+
144+
_, err := tk.Exec("drop table mysql.gc_delete_range")
145+
c.Assert(err, NotNil)
140146
}
141147

142148
func (s *testSuite) TestCreateDropIndex(c *C) {

0 commit comments

Comments
 (0)