Skip to content
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: fix drop user bug #6624

Merged
merged 16 commits into from
Jun 6, 2018
Merged

Conversation

zhexuany
Copy link
Contributor

@zhexuany zhexuany commented May 23, 2018


mysql> create database tidb;
Query OK, 0 rows affected (0.01 sec)

mysql> 
mysql> select * from mysql.db;
Empty set (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON tidb.* TO 'tidb'@'%' WITH GRANT OPTION;
Query OK, 1 row affected (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> drop user 'tidb'@'%';
Query OK, 0 rows affected (0.01 sec)

mysql> 
mysql> select * from mysql.db\G;
*************************** 1. row ***************************
                 Host: %
                   DB: tidb
                 User: tidb
          Select_priv: Y
          Insert_priv: Y
          Update_priv: Y
          Delete_priv: Y
          Create_priv: Y
            Drop_priv: Y
           Grant_priv: Y
      References_priv: N
           Index_priv: Y
           Alter_priv: Y
Create_tmp_table_priv: N
     Lock_tables_priv: N
     Create_view_priv: N
       Show_view_priv: N
  Create_routine_priv: N
   Alter_routine_priv: N
         Execute_priv: Y
           Event_priv: N
         Trigger_priv: N
1 row in set (0.00 sec)


mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from mysql.db\G;
*************************** 1. row ***************************
                 Host: %
                   DB: tidb
                 User: tidb
          Select_priv: Y
          Insert_priv: Y
          Update_priv: Y
          Delete_priv: Y
          Create_priv: Y
            Drop_priv: Y
           Grant_priv: Y
      References_priv: N
           Index_priv: Y
           Alter_priv: Y
Create_tmp_table_priv: N
     Lock_tables_priv: N
     Create_view_priv: N
       Show_view_priv: N
  Create_routine_priv: N
   Alter_routine_priv: N
         Execute_priv: Y
           Event_priv: N
         Trigger_priv: N
1 row in set (0.00 sec)
MySQL 5.7

{code:sql}
MySQL [(none)]> show schemas;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.00 sec)


MySQL [(none)]> create database tidb;
Query OK, 1 row affected (0.00 sec)

MySQL [(none)]> CREATE USER 'tidb'@'%' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

MySQL [(none)]> GRANT ALL PRIVILEGES ON tidb.* TO 'tidb'@'%' WITH GRANT OPTION;
Query OK, 0 rows affected (0.00 sec)

MySQL [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mysql.db\G;
*************************** 1. row ***************************
                 Host: localhost
                   Db: performance_schema
                 User: mysql.session
          Select_priv: Y
          Insert_priv: N
          Update_priv: N
          Delete_priv: N
          Create_priv: N
            Drop_priv: N
           Grant_priv: N
      References_priv: N
           Index_priv: N
           Alter_priv: N
Create_tmp_table_priv: N
     Lock_tables_priv: N
     Create_view_priv: N
       Show_view_priv: N
  Create_routine_priv: N
   Alter_routine_priv: N
         Execute_priv: N
           Event_priv: N
         Trigger_priv: N
*************************** 2. row ***************************
                 Host: localhost
                   Db: sys
                 User: mysql.sys
          Select_priv: N
          Insert_priv: N
          Update_priv: N
          Delete_priv: N
          Create_priv: N
            Drop_priv: N
           Grant_priv: N
      References_priv: N
           Index_priv: N
           Alter_priv: N
Create_tmp_table_priv: N
     Lock_tables_priv: N
     Create_view_priv: N
       Show_view_priv: N
  Create_routine_priv: N
   Alter_routine_priv: N
         Execute_priv: N
           Event_priv: N
         Trigger_priv: Y
*************************** 3. row ***************************
                 Host: %
                   Db: tidb
                 User: tidb
          Select_priv: Y
          Insert_priv: Y
          Update_priv: Y
          Delete_priv: Y
          Create_priv: Y
            Drop_priv: Y
           Grant_priv: Y
      References_priv: Y
           Index_priv: Y
           Alter_priv: Y
Create_tmp_table_priv: Y
     Lock_tables_priv: Y
     Create_view_priv: Y
       Show_view_priv: Y
  Create_routine_priv: Y
   Alter_routine_priv: Y
         Execute_priv: Y
           Event_priv: Y
         Trigger_priv: Y
3 rows in set (0.00 sec)

MySQL [(none)]> drop user 'tidb'@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mysql.db\G;
*************************** 1. row ***************************
                 Host: localhost
                   Db: performance_schema
                 User: mysql.session
          Select_priv: Y
          Insert_priv: N
          Update_priv: N
          Delete_priv: N
          Create_priv: N
            Drop_priv: N
           Grant_priv: N
      References_priv: N
           Index_priv: N
           Alter_priv: N
Create_tmp_table_priv: N
     Lock_tables_priv: N
     Create_view_priv: N
       Show_view_priv: N
  Create_routine_priv: N
   Alter_routine_priv: N
         Execute_priv: N
           Event_priv: N
         Trigger_priv: N
*************************** 2. row ***************************
                 Host: localhost
                   Db: sys
                 User: mysql.sys
          Select_priv: N
          Insert_priv: N
          Update_priv: N
          Delete_priv: N
          Create_priv: N
            Drop_priv: N
           Grant_priv: N
      References_priv: N
           Index_priv: N
           Alter_priv: N
Create_tmp_table_priv: N
     Lock_tables_priv: N
     Create_view_priv: N
       Show_view_priv: N
  Create_routine_priv: N
   Alter_routine_priv: N
         Execute_priv: N
           Event_priv: N
         Trigger_priv: Y
2 rows in set (0.00 sec)

@zhexuany
Copy link
Contributor Author

After drop user, mysql.db does not have any row related with user which was intended to drop but tidb has such row. This PR fixes this.

} else {
sql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = "%s" and User = "%s";`, mysql.SystemDB, mysql.DBTable, user.Hostname, user.Username)
}
sql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = "%s" and User = "%s";`, mysql.SystemDB, mysql.DBTable, user.Hostname, user.Username)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line?

@@ -232,6 +232,13 @@ func (e *SimpleExec) executeDropUser(s *ast.DropUserStmt) error {
}
sql := fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = "%s" and User = "%s";`, mysql.SystemDB, mysql.UserTable, user.Hostname, user.Username)
_, _, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This err will be overwritten.

Copy link
Contributor

@winkyao winkyao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address comment, reset LGTM

@zhexuany
Copy link
Contributor Author

/run-all-tests

@shenli
Copy link
Member

shenli commented May 23, 2018

@zhexuany We need to clean up data in the tables_priv and columns_priv.

/cc @tiancaiamao

@zhexuany
Copy link
Contributor Author

@tiancaiamao PTAL

@@ -235,6 +235,22 @@ func (e *SimpleExec) executeDropUser(s *ast.DropUserStmt) error {
if err != nil {
failedUsers = append(failedUsers, user.String())
}

// delete privileges from mysql.db
sql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = "%s" and User = "%s";`, mysql.SystemDB, mysql.DBTable, user.Hostname, user.Username)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about use a transaction to run the three delete statements? Or it will leave some grabege when meet something wrong.

Copy link
Contributor

@tiancaiamao tiancaiamao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test MySQL's behavior:

begin
insert into t value (1)
drop user tidb
rollback
select * from t

_, _, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
if err != nil {
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), sql); err != nil {
failedUsers = append(failedUsers, user.String())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unlikely to meet a error here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? For example all the tikv nodes are down.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before commit, all the operation is cached in union store @shenli

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete statement need to get data from tikv first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the err is not nil, we should return error.


//TODO: (tidb-team) need delete columns_priv once we implement columns_priv functionality.
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "commit"); err != nil {
return errors.Trace(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

failedUsers = append(failedUsers, user.String())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotcha.

if err != nil {
return errors.Trace(err)
}
// err := e.ctx.Txn().Commit(sessionctx.SetCommitCtx(context.Background(), e.ctx))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean up the code

@zhexuany
Copy link
Contributor Author

@shenli @tiancaiamao PTAL


// begin a transaction to delete a user.
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "begin"); err != nil {
fmt.Println(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove debug log

_, _, err = e.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(e.ctx, sql)
if err != nil {
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), sql); err != nil {
failedUsers = append(failedUsers, user.String())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before commit, all the operation is cached in union store @shenli

@tiancaiamao
Copy link
Contributor

Will MySQL drop user tidb auto commit current transaction? what's its behavior? @zhexuany

@zhexuany
Copy link
Contributor Author

I will be auto committed. @tiancaiamao

@zhexuany
Copy link
Contributor Author

@shenli @tiancaiamao PTAL again.

@tiancaiamao
Copy link
Contributor

LGTM

@tiancaiamao tiancaiamao added the status/LGT1 Indicates that a PR has LGTM 1. label May 30, 2018

// delete privileges from mysql.db
sql = fmt.Sprintf(`DELETE FROM %s.%s WHERE Host = "%s" and User = "%s";`, mysql.SystemDB, mysql.DBTable, user.Hostname, user.Username)
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), sql); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@zhexuany
Copy link
Contributor Author

zhexuany commented Jun 4, 2018

@shenli PTAL

failedUsers = append(failedUsers, user.String())
}

//TODO: (tidb-team) need delete columns_priv once we implement columns_priv functionality.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to add "(tidb-team)" in todo

@zhexuany
Copy link
Contributor Author

zhexuany commented Jun 4, 2018

@zz-jason PTAL again.

err := e.ctx.Txn().Commit(sessionctx.SetCommitCtx(context.Background(), e.ctx))
if err != nil {
return errors.Trace(err)
}
errMsg := "Operation DROP USER failed for " + strings.Join(failedUsers, ",")
return terror.ClassExecutor.New(CodeCannotUser, errMsg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to execute rollback when len(failedUsers) > 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need. I just update accordingly.

"localhost test testDB1 Y Y Y Y Y Y Y N Y Y N N N N N N Y N N] [% dddb_% dduser Y Y Y Y Y Y Y N Y Y N N N N N N Y N N",
"% test test Y N N N N N N N N N N N N N N N N N N",
"localhost test testDBRevoke N N N N N N N N N N N N N N N N N N N",
))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need another test like dropping a user which not exists?

@shenli
Copy link
Member

shenli commented Jun 6, 2018

LGTM

@shenli shenli added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Jun 6, 2018
@zhexuany
Copy link
Contributor Author

zhexuany commented Jun 6, 2018

/run-all-test


createUserSQL = `CREATE USER 'test1'@'localhost'`
createUserSQL = `CREATE USER 'test2'@'localhost'`
tk.Exec(createUserSQL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use MustExec?

Copy link
Member

@zz-jason zz-jason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zhexuany zhexuany merged commit 7227db3 into pingcap:master Jun 6, 2018
@zhexuany zhexuany deleted the fix_drop_user_bug branch June 6, 2018 09:13
zhexuany added a commit to zhexuany/tidb that referenced this pull request Jul 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/LGT2 Indicates that a PR has LGTM 2.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants