Should flush privileges follow after grant?

Content source: Lin Xiaobin "45 Lectures on MySQL Actual Combat"

In MySQL, the grant statement is used to grant rights to users. It is mentioned in some operation documents that a flush privileges command must be executed immediately after grant to make the grant statement take effect. When I first used MySQL, I followed the instructions in an operating document and followed this order. So, do flush privileges really need to be executed after grant? If the flush command is not executed, can the empower statement really not take effect?

First create a user: create user'ua'@'%' identified by'pa';

In MySQL, user name (user) + address (host) only represents a user, so ua@ip1 and ua@ip2 represent two different users. This command does two actions:

  • On the disk, insert a row into the mysql.user table. Since there is no specified permission, the value of all the permission fields on this row of data is N;
  • In the memory, insert an acl_user object into the array acl_users, the access field of this object is 0.

    

Global permissions

Acting on the entire MySQL instance, these permissions information is stored in the user table of the mysql library. If I want to give the user ua a highest authority, the sentence is like this:
grant all privileges on *.* to'ua'@'%' with grant option;

This grant command does two actions:

  • On the disk, in the mysql.user table, modify the values ​​of all the fields indicating permissions in the row of the user'ua'@'%' to'Y';
  • In the memory, find the object corresponding to this user from the array acl_users, and modify the access value (permission bit) to binary "all 1s".

After the grant command is executed, if a new client successfully logs in with the username ua, MySQL will maintain a thread object for the new connection, and then check the user's permissions from the acl_users array, and copy the permission value to this Thread object. In the subsequent statements executed in this connection, all judgments about global permissions directly use the permission bits stored inside the thread object.

Based on the above analysis, we can know:

  • The grant command updates the disk and memory at the same time for global permissions. The command will take effect immediately after completion, and the newly created connection will use the new permissions.
  • For an existing connection, its global permissions are not affected by the grant command.

If you want to reclaim the permissions granted by the above grant statement, you can use the following command: revoke all privileges on *.* from'ua'@'%';

The usage of this revoke command is similar to grant, and it does the following two actions:

  • On the disk, in the mysql.user table, modify the values ​​of all the fields that indicate permissions in the row of the user'ua'@'%' to "N";
  • In the memory, find the object corresponding to this user from the array acl_users, and modify the value of access to 0.

db permissions

If you want the user ua to have all the permissions of the library db1, you can execute the following command: grant all privileges on db1.* to'ua'@'%' with grant option;

The database-based permission records are stored in the mysql.db table and in the memory in the array acl_dbs. This grant command does the following two actions:

  • On the disk, a row of records was inserted into the mysql.db table, and all the permission bit fields were set to "Y";
  • In the memory, add an object to the array acl_dbs, the permission bit of this object is "all 1".

    

Every time you need to determine the read and write permissions of a user to a database, you need to traverse the acl_dbs array once, find the matching object according to user, host, and db, and then judge according to the permission bit of the object. In other words, when grant modifies db permissions, it takes effect on both disk and memory.

The effect of grant operation on existing connections is different between global permissions and db-based permissions. Next, we will do a controlled experiment to take a look at each.

    

Note: The operation of set global sync_binlog requires super permission.

It can be seen that although the super permission of user ua has been recovered through the revoke statement at T3, the permission verification still passed when set global was executed at T4. This is because super is a global authority, this authority information is in the thread object, and the revoke operation does not affect this thread object.

After removing all the permissions of ua to the db1 library at T5, if session B operates the table of the db1 library at T6, an error "Insufficient permissions" will be reported. This is because acl_dbs is a global array, and all threads use this array to determine db permissions, so that the revoke operation will immediately affect session B.

There is a special logic in the code implementation. If the current session is already in a certain db, the library permissions obtained when the library was used before will be stored in the session variable.

You can see that at time T6, session C and session B have the same operation logic on table t. But session B reports an error, and session C can execute successfully. This is because the use db1 executed by session C at time T2 has obtained the permissions of this library. Before switching out of the db1 library, session C has always had permissions on this library.

Table permissions and column permissions

MySQL supports more fine-grained table permissions and column permissions. Among them, the table permission definition is stored in the table mysql.tables_priv, and the column permission definition is stored in the table mysql.columns_priv. These two types of permissions are combined and stored in the memory hash structure column_priv_hash.

The authorization commands for these two types of permissions are as follows:

create table db1.t1(id int, a int);
grant all privileges on db1.t1 to 'ua'@'%' with grant option;
GRANT SELECT(id), INSERT (id,a) ON mydb.mytbl TO 'ua'@'%' with grant option;

Similar to the db permissions, these two permissions modify the data table every time they grant and also modify the hash structure in the memory simultaneously. Therefore, operations on these two types of permissions will also immediately affect existing connections.

flush privileges 

The flush privileges command will clear the acl_users array, then read the data from the mysql.user table and reload it to reconstruct an acl_users array. In other words, based on the data in the data table, the global permission memory array will be reloaded again. Similarly, MySQL has done the same for db permissions, table permissions, and column permissions.

In other words, if the permission data of the memory and the disk data table are the same, there is no need to execute flush privileges. And if we all use grant/revoke statements to execute, the memory and data tables are originally kept updated synchronously.

Therefore, under normal circumstances, after the grant command, there is no need to execute the flush privileges command.

scenes to be used:

When the privilege data in the data table is inconsistent with the privilege data in the memory, the flush privileges statement can be used to reconstruct the memory data to reach a consistent state.

This inconsistency is often caused by irregular operations, such as directly using DML statements to operate the permission table, which causes the permission data in the data table to be inconsistent with the permission data in the memory.

In addition, when using the grant statement to grant authorization, you will often see this way of writing:
grant super on *.* to'ua'@'%' identified by'pa';

This command adds identified by'password'. In addition to the authorization, the logic of the statement also contains:

  • If the user'ua'@'%' does not exist, create this user, the password is pa;
  • If user ua already exists, change the password to pa.

 

Guess you like

Origin blog.csdn.net/qq_24436765/article/details/112767915