@@ -156,6 +156,13 @@ func (e *DDLExec) executeCreateIndex(s *ast.CreateIndexStmt) error {
156
156
157
157
func (e * DDLExec ) executeDropDatabase (s * ast.DropDatabaseStmt ) error {
158
158
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
+
159
166
err := domain .GetDomain (e .ctx ).DDL ().DropSchema (e .ctx , dbName )
160
167
if infoschema .ErrDatabaseNotExists .Equal (err ) {
161
168
if s .IfExists {
@@ -179,6 +186,24 @@ func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error {
179
186
return errors .Trace (err )
180
187
}
181
188
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
+
182
207
func (e * DDLExec ) executeDropTable (s * ast.DropTableStmt ) error {
183
208
var notExistTables []string
184
209
for _ , tn := range s .Tables {
@@ -198,6 +223,12 @@ func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
198
223
return errors .Trace (err )
199
224
}
200
225
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
+
201
232
if config .CheckTableBeforeDrop {
202
233
log .Warnf ("admin check table `%s`.`%s` before drop." , fullti .Schema .O , fullti .Name .O )
203
234
sql := fmt .Sprintf ("admin check table `%s`.`%s`" , fullti .Schema .O , fullti .Name .O )
0 commit comments