-
Dmitry Shulga authored
For mysql server started with GTID_MODE=ON concurrent running of the statements SHOW TABLE STATUS and REVOKE ALL PRIVILEGES could lead to deadlock in case there is a view in database and REVOKE ALL PRIVILEGES partially failed for some of requested users, that is some users are handled successfully and some of them are failed. The reason for deadlock is that SHOW TABLE STATUS acquires the lock LOCK_grant within mysql_make_view() while holding LOCK_open whereas REVOKE ALL PRIVILEGES acquires LOCK_open holding LOCK_grant. The sequence of acquiring LOCK_grant, LOCK_open while handling REVOKE ALL PRIVILEGES happens only for the case when some of users listed in the statement arguments are handled successfully and some of them are failed AND the server is started with GTID_MODE=ON. In this case mysql_revoke_all() calls MYSQL_BIN_LOG::write_incident() that finally call open_table() on behalf of Gtid_table_access_context::init(). On the other hand, acquiring of locks in the order LOCK_open, LOCK_grant while handling the statement SHOW TABLE STATUS happens in case there is a view and mysql_make_view() is called from open_table(). There are two approaches to resolve this issue. The first one is to release LOCK_grant before calling MYSQL_BIN_LOG::write_incident() while handling REVOKE ALL PRIVILEGES. This modification could led potentially to reordering in binlog of statement REVOKE ALL PRIVILEGES with other statements running at the same moment. So this approach is too risky. The second one is to release LOCK_open just right after a view definition was read from the data dictionary. The second approach forces us to make refactoring that splits mysql_make_view() into two functions: open_and_read_view() and parse_view_definition(), replaces all occurences of mysql_make_view() by these two functions and releases LOCK_open just right after open_and_read_view() returned. To have a test case for this bug the function check_table_access() was modified in order to return immediately in case the debug variable force_check_table_access_return_ok is set. This allows to execute SET DEBUG_SYNC='...' from the test case while holding LOCK_grant.
Dmitry Shulga authoredFor mysql server started with GTID_MODE=ON concurrent running of the statements SHOW TABLE STATUS and REVOKE ALL PRIVILEGES could lead to deadlock in case there is a view in database and REVOKE ALL PRIVILEGES partially failed for some of requested users, that is some users are handled successfully and some of them are failed. The reason for deadlock is that SHOW TABLE STATUS acquires the lock LOCK_grant within mysql_make_view() while holding LOCK_open whereas REVOKE ALL PRIVILEGES acquires LOCK_open holding LOCK_grant. The sequence of acquiring LOCK_grant, LOCK_open while handling REVOKE ALL PRIVILEGES happens only for the case when some of users listed in the statement arguments are handled successfully and some of them are failed AND the server is started with GTID_MODE=ON. In this case mysql_revoke_all() calls MYSQL_BIN_LOG::write_incident() that finally call open_table() on behalf of Gtid_table_access_context::init(). On the other hand, acquiring of locks in the order LOCK_open, LOCK_grant while handling the statement SHOW TABLE STATUS happens in case there is a view and mysql_make_view() is called from open_table(). There are two approaches to resolve this issue. The first one is to release LOCK_grant before calling MYSQL_BIN_LOG::write_incident() while handling REVOKE ALL PRIVILEGES. This modification could led potentially to reordering in binlog of statement REVOKE ALL PRIVILEGES with other statements running at the same moment. So this approach is too risky. The second one is to release LOCK_open just right after a view definition was read from the data dictionary. The second approach forces us to make refactoring that splits mysql_make_view() into two functions: open_and_read_view() and parse_view_definition(), replaces all occurences of mysql_make_view() by these two functions and releases LOCK_open just right after open_and_read_view() returned. To have a test case for this bug the function check_table_access() was modified in order to return immediately in case the debug variable force_check_table_access_return_ok is set. This allows to execute SET DEBUG_SYNC='...' from the test case while holding LOCK_grant.
Loading