-
Sujatha Sivakumar authored
--SUPER-READ-ONLY OPTION Problem: ======== After upgrading MySQL server from 5.7.17 to 5.7.18 'mysqlrplsync' utility tool fails with following error. ERROR: Query failed. 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement When this occurs, the Slave_SQL_Running on the slave server stops running and needs to be manually started again. The slave server does have the super-read-only option set to true. When running MySQL 5.7.17 this wasn't an issue. Analysis: ======== When replication information repository is set to 'TABLE' few replication specific administration commands listed below, will try to update the repository tables. 1) START SLAVE 2) STOP SLAVE 3) CHANGE MASTER 4) RESET SLAVE 5) RESET MASTER 6) SET GLOBAL GTID_PURGED 7) FLUSH BINARY LOGS 8) 'gtid_executed' TABLE compression thread. First three commands were fixed as part of Bug#22097534: SUPER_READ_ONLY ABORTS STOP SLAVE IF RELAY_LOG_INFO_REPOSITORY=TABLE, DBG CRASH The reset of the commands were fixed as part of Bug#22857926: ASSERTION `! IS_SET()' AT SQL_ERROR.CC:38 IN READ_ONLY MODE FOR MANY RPL CMDS. During the Bug#22857926 fix, the previous Bug#22097534 fix specific changes were reverted a new approach was taken. The new approach used a flag named 'ignore_global_read_lock' whose intention is to ignore the read only option and allow commits to replication specific system tables. If this flag is set then the additional check for 'read only' option is not done. But the above fix works fine only when 'AUTOCOMMIT=ON'. In the case of AUTOCOMMIT=OFF the 'ignore_global_read_lock' flag is not set. Hence commands fail to ignore read_only restriction. STOP SLAVE command behavior explained in detail: STOP SLAVE command is an IMPLICIT COMMIT command, i.e parser will append an explicit BEGIN and COMMIT for this command. BEGIN STOP SLAVE; COMMIT; STOP SLAVE command will try to stop both the applier thread and receiver thread and update their positions in 'slave_relay_log_info' and 'slave_master_info' tables. Case: AUTOCOMMIT=ON. 1) BEGIN 2) Update 'slave_relay_log_info' table and commit as a real transaction. System_table_access::close_table will invoke ha_commit_trans with 'ignore_global_read_lock=true'. Since autocommit is 'ON' each statement will do a complete commit and clean up the transaction context. 3) Update 'slave_master_info' also does the same. 4) COMMIT. COMMIT will invoke 'trans_commit_implicit'. It will check if there any active transactions which needs to be committed implicitly. Since step 2-3 are real commit transactions this final commit has nothing to do. It will exit without proceeding further. Case: AUTOCOMMIT=OFF. 1) BEGIN 2) Update 'slave_relay_log_info' table. This transaction is considered as a multi statement transaction mode, it will not commit on its own. It will wait for final COMMIT execution. 3) Update 'slave_master_info' also does the same. 4) COMMIT. COMMIT will invoke 'trans_commit_implicit'. It will check if there any active transactions which needs to be committed . Since there are active transaction sessions from step 2-3 'ha_commit_trans' will be called as shown below. 'trans_commit_implicit' will invoke ha_commit_trans (thd,all=true,ignore_global_read_lock=false) This will not pass the read_only check and the command will fail. This issue happens for commands that update info tables other than 'gtid_executed' table. In case of 'gtid_executed' table irrespective of autocommit variable all the transactions are considered as 'real' transactions and they will do complete commit. Fix: === Introduced a new variable, to flag the sql command under execution to ignore the read_only/super_read_only. If the variable is set then the command is allowed to execute even though read_only/super_read_only is enabled otherwise command is blocked.
Sujatha Sivakumar authored--SUPER-READ-ONLY OPTION Problem: ======== After upgrading MySQL server from 5.7.17 to 5.7.18 'mysqlrplsync' utility tool fails with following error. ERROR: Query failed. 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement When this occurs, the Slave_SQL_Running on the slave server stops running and needs to be manually started again. The slave server does have the super-read-only option set to true. When running MySQL 5.7.17 this wasn't an issue. Analysis: ======== When replication information repository is set to 'TABLE' few replication specific administration commands listed below, will try to update the repository tables. 1) START SLAVE 2) STOP SLAVE 3) CHANGE MASTER 4) RESET SLAVE 5) RESET MASTER 6) SET GLOBAL GTID_PURGED 7) FLUSH BINARY LOGS 8) 'gtid_executed' TABLE compression thread. First three commands were fixed as part of Bug#22097534: SUPER_READ_ONLY ABORTS STOP SLAVE IF RELAY_LOG_INFO_REPOSITORY=TABLE, DBG CRASH The reset of the commands were fixed as part of Bug#22857926: ASSERTION `! IS_SET()' AT SQL_ERROR.CC:38 IN READ_ONLY MODE FOR MANY RPL CMDS. During the Bug#22857926 fix, the previous Bug#22097534 fix specific changes were reverted a new approach was taken. The new approach used a flag named 'ignore_global_read_lock' whose intention is to ignore the read only option and allow commits to replication specific system tables. If this flag is set then the additional check for 'read only' option is not done. But the above fix works fine only when 'AUTOCOMMIT=ON'. In the case of AUTOCOMMIT=OFF the 'ignore_global_read_lock' flag is not set. Hence commands fail to ignore read_only restriction. STOP SLAVE command behavior explained in detail: STOP SLAVE command is an IMPLICIT COMMIT command, i.e parser will append an explicit BEGIN and COMMIT for this command. BEGIN STOP SLAVE; COMMIT; STOP SLAVE command will try to stop both the applier thread and receiver thread and update their positions in 'slave_relay_log_info' and 'slave_master_info' tables. Case: AUTOCOMMIT=ON. 1) BEGIN 2) Update 'slave_relay_log_info' table and commit as a real transaction. System_table_access::close_table will invoke ha_commit_trans with 'ignore_global_read_lock=true'. Since autocommit is 'ON' each statement will do a complete commit and clean up the transaction context. 3) Update 'slave_master_info' also does the same. 4) COMMIT. COMMIT will invoke 'trans_commit_implicit'. It will check if there any active transactions which needs to be committed implicitly. Since step 2-3 are real commit transactions this final commit has nothing to do. It will exit without proceeding further. Case: AUTOCOMMIT=OFF. 1) BEGIN 2) Update 'slave_relay_log_info' table. This transaction is considered as a multi statement transaction mode, it will not commit on its own. It will wait for final COMMIT execution. 3) Update 'slave_master_info' also does the same. 4) COMMIT. COMMIT will invoke 'trans_commit_implicit'. It will check if there any active transactions which needs to be committed . Since there are active transaction sessions from step 2-3 'ha_commit_trans' will be called as shown below. 'trans_commit_implicit' will invoke ha_commit_trans (thd,all=true,ignore_global_read_lock=false) This will not pass the read_only check and the command will fail. This issue happens for commands that update info tables other than 'gtid_executed' table. In case of 'gtid_executed' table irrespective of autocommit variable all the transactions are considered as 'real' transactions and they will do complete commit. Fix: === Introduced a new variable, to flag the sql command under execution to ignore the read_only/super_read_only. If the variable is set then the command is allowed to execute even though read_only/super_read_only is enabled otherwise command is blocked.
Loading