-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
executor: forbid user to drop important system table #7471
Conversation
If a user drop some important tables by mistake, such as mysql.user, it's difficult to recover. In the worst case, the whole cluster fails to bootstrap, we should prevent that.
@@ -198,6 +230,14 @@ 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about forbidding drop any tables in database mysql
? It can avoid we add some important table in mysql, and forget to modify the systemTables map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's your opinion? @shenli @lamxTyler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest protecting all the tables in the mysql
database.
executor/ddl.go
Outdated
// 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" { | ||
if !privileges.SkipWithGrant { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we need to consider the privileges.SkipWithGrant
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's a rare case, but how about that we really want to do it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a "backdoor".
@@ -198,6 +230,14 @@ 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest protecting all the tables in the mysql
database.
executor/ddl.go
Outdated
@@ -154,8 +155,19 @@ func (e *DDLExec) executeCreateIndex(s *ast.CreateIndexStmt) error { | |||
return errors.Trace(err) | |||
} | |||
|
|||
var errForbidDrop = errors.New("Hey, drop system database/table, are you sure?") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make the error message more seriously.
"gc_delete_range_done": {}, | ||
} | ||
|
||
func isSystemTable(schema, table string) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we put it to infoschema.go? I think it is like "IsMemoryDB", we can put these together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is removed, we forbid dropping tables in "mysql" database.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we forbid drop all the tables in the database "mysql", I think the user will blame that he cannot drop the table which he created in the database "mysql", except using skip_grand_table
which requires to restart the tidb server.
A sane person will not drop system tables. |
I think this will break mysqldump restores. Here is an example of what mysqldump with --all-databases from 5.7 produces:
|
"A sane person will not create table on "mysql" database" ? Maybe s/sane/genius/ will be all right :-) |
@morgo Some tables in the @tiancaiamao |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
PTAL @shenli |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/run-all-tests |
PTAL @shenli |
executor/ddl.go
Outdated
// 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.Trace(errForbidDrop) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the system table name in the error message.
executor/ddl.go
Outdated
@@ -179,6 +188,22 @@ func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error { | |||
return errors.Trace(err) | |||
} | |||
|
|||
var systemTables = map[string]struct{}{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for this map. Explain why we prevent users from dropping them.
8005880
to
d872685
Compare
PTAL @shenli |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What problem does this PR solve?
If a user drop some important tables by mistake, such as mysql.user, it's difficult to recover.
In the worst case, the whole cluster fails to bootstrap, we should prevent that.
What is changed and how it works?
Forbid user to drop important system tables.
Check List
Tests
Side effects
It's harder to drop those tables.
Should we also protect the statistic tables? @lamxTyler
@zimulala @shenli