-
Venkatesh Duggirala authored
WITH REPEATABLE READ Problem and Analysis -------------------- Because of the use of MTS and/or XA transactions, the order statements from distinct transactions were originally applied on the master may not be the same order they are applied on the slave. On those cases, using RBR with a transaction isolation level other than READ COMMITTED might might lead to blocking conditions that didn't happened on the original workload (see BUG#25082593). Fix --- We are now using a flag on the [Anonymous_gtid|Gtid]_log_event stating if the transaction might have changes logged with statements. When this flag is set (default for non-fixed servers) the slave will not change the applier thread transaction isolation level. When the flag is not set, the applier will set the transaction isolation level of the current transaction to READ COMMITTED if necessary (it will not change it when the applier session isolation level be equal or less restrictive than READ COMMITTED). In this way, we are forcing that all transactions replicated using row based replication will always use the READ COMMITTED transaction isolation level on the slave side, regardless of any server transaction isolation level configuration. The fix also restored the applier session transaction isolation level after applying a Xid_log_event (after committing a replicated transaction), a XA_prepare_log_event (after preparing a replicated transaction) and in the cases of aborted/failed transactions. The mysqlbinlog dump of a transaction flagged as "rbr_only" will also include a "SET TRANSACTION ISOLATION LEVEL" statement when dumping the GTID event. Changed files: @ libbinlogevents/include/control_events.h We gave a meaning to the already logged flag information. @ libbinlogevents/src/control_events.cpp Processed the GTID flags, collecting the "might_have_sbr_stmts" info. @ plugin/replication_observers_example/replication_observers_example.cc @ rapid/plugin/group_replication/src/observer_trans.cc @ rapid/plugin/group_replication/src/handlers/certification_handler.cc Fixed calls to GTID constructor. @ sql/binlog.cc Created a new flag at "binlog_cache_data" named "with_sbr" that is set true when the cache is fed with non-terminal query event. Created a new flag at "binlog_cache_data" named "with_rbr" that is set true when the cache is fed with Table_map or Rows event. Created also the "might_have_sbr_stmts" function, that returns false for "pure RBR" transactions. This new function was implemented for the "binlog_cache_data". Added the logic to reset and set the new flags at "binlog_cache_data::reset" and "binlog_cache_data::write_event", and also to preserve the flags upon "SAVEPOINT/ROLLBACK TO SAVEPOINT". Made "MYSQL_BIN_LOG::write_gtid" to consider the cache information about the binary log content when creating the Gtid_log_event. @ sql/log_event.h Updated "Query_log_event::is_trans_keyword()" to recognize XA transactions terminal keywords that should not be considered as statements changing content. Created a new function "Log_event::is_sbr_logging_format()" that will return true if the event was/has to be logged using SBR and does not contains a transaction control statement. Created a new function "Log_event::is_rbr_logging_format()" that will return true if the event was/has to be logged using RBR. @ sql/log_event.cc We will stop the applier with an error when we assumed the transaction as "rbr_only" and some statement changing content be applied. Restored the applier session transaction isolation level after applying a Xid_log_event (after committing a replicated transaction), a XA_prepare_log_event (after preparing a replicated transaction) and in the cases of aborted/failed transactions. "Gtid_log_event::print" will now also print "rbr_only=[yes|no]" when dumping a Gtid_log_event with mysqlbinlog. It will also include a "SET TRANSACTION ISOLATION LEVEL READ COMMITTED" statement when dumping the GTID event with "rbr_only=yes". "Gtid_log_event::write_post_header_to_memory" now computes the GTID flags field instead of just writing "1" to it. "Gtid_log_event::do_apply_event" now set the transaction isolation level to READ COMMITTED when the "might_have_sbr_stmts" flag be false. Note that we don't change the isolation level for skipped GTID and when the isolation level be less restrictive than READ COMMITTED.
Venkatesh Duggirala authoredWITH REPEATABLE READ Problem and Analysis -------------------- Because of the use of MTS and/or XA transactions, the order statements from distinct transactions were originally applied on the master may not be the same order they are applied on the slave. On those cases, using RBR with a transaction isolation level other than READ COMMITTED might might lead to blocking conditions that didn't happened on the original workload (see BUG#25082593). Fix --- We are now using a flag on the [Anonymous_gtid|Gtid]_log_event stating if the transaction might have changes logged with statements. When this flag is set (default for non-fixed servers) the slave will not change the applier thread transaction isolation level. When the flag is not set, the applier will set the transaction isolation level of the current transaction to READ COMMITTED if necessary (it will not change it when the applier session isolation level be equal or less restrictive than READ COMMITTED). In this way, we are forcing that all transactions replicated using row based replication will always use the READ COMMITTED transaction isolation level on the slave side, regardless of any server transaction isolation level configuration. The fix also restored the applier session transaction isolation level after applying a Xid_log_event (after committing a replicated transaction), a XA_prepare_log_event (after preparing a replicated transaction) and in the cases of aborted/failed transactions. The mysqlbinlog dump of a transaction flagged as "rbr_only" will also include a "SET TRANSACTION ISOLATION LEVEL" statement when dumping the GTID event. Changed files: @ libbinlogevents/include/control_events.h We gave a meaning to the already logged flag information. @ libbinlogevents/src/control_events.cpp Processed the GTID flags, collecting the "might_have_sbr_stmts" info. @ plugin/replication_observers_example/replication_observers_example.cc @ rapid/plugin/group_replication/src/observer_trans.cc @ rapid/plugin/group_replication/src/handlers/certification_handler.cc Fixed calls to GTID constructor. @ sql/binlog.cc Created a new flag at "binlog_cache_data" named "with_sbr" that is set true when the cache is fed with non-terminal query event. Created a new flag at "binlog_cache_data" named "with_rbr" that is set true when the cache is fed with Table_map or Rows event. Created also the "might_have_sbr_stmts" function, that returns false for "pure RBR" transactions. This new function was implemented for the "binlog_cache_data". Added the logic to reset and set the new flags at "binlog_cache_data::reset" and "binlog_cache_data::write_event", and also to preserve the flags upon "SAVEPOINT/ROLLBACK TO SAVEPOINT". Made "MYSQL_BIN_LOG::write_gtid" to consider the cache information about the binary log content when creating the Gtid_log_event. @ sql/log_event.h Updated "Query_log_event::is_trans_keyword()" to recognize XA transactions terminal keywords that should not be considered as statements changing content. Created a new function "Log_event::is_sbr_logging_format()" that will return true if the event was/has to be logged using SBR and does not contains a transaction control statement. Created a new function "Log_event::is_rbr_logging_format()" that will return true if the event was/has to be logged using RBR. @ sql/log_event.cc We will stop the applier with an error when we assumed the transaction as "rbr_only" and some statement changing content be applied. Restored the applier session transaction isolation level after applying a Xid_log_event (after committing a replicated transaction), a XA_prepare_log_event (after preparing a replicated transaction) and in the cases of aborted/failed transactions. "Gtid_log_event::print" will now also print "rbr_only=[yes|no]" when dumping a Gtid_log_event with mysqlbinlog. It will also include a "SET TRANSACTION ISOLATION LEVEL READ COMMITTED" statement when dumping the GTID event with "rbr_only=yes". "Gtid_log_event::write_post_header_to_memory" now computes the GTID flags field instead of just writing "1" to it. "Gtid_log_event::do_apply_event" now set the transaction isolation level to READ COMMITTED when the "might_have_sbr_stmts" flag be false. Note that we don't change the isolation level for skipped GTID and when the isolation level be less restrictive than READ COMMITTED.
Loading