Description:
In 5.7, GTIDs can be enabled even if log-bin is not enabled or log-slave-updates is not enabled. In this case, when a transactions with a GTID is committed, the GTID is added to the table mysql.gtid_executed.
Since 5.6, @@GLOBAL.GTID_PURGED contains the set of GTIDs which are included in @@GLOBAL.GTID_EXECUTED but not in the binary log.
However, when a transaction is committed and the binary log is off, the GTID is not included in @@GLOBAL.GTID_PURGED.
The GTID is added to @@GLOBAL.GTID_PURGED the next time the server restarts, since the procedure to read GTIDs from the binary log on server start is correct. But the GTID should be added to @@GLOBAL.GTID_PURGED already when the transaction is committed.
How to repeat:
--source include/have_gtid.inc
--source include/master-slave.inc
CREATE TABLE t1 (a INT);
--source include/sync_slave_sql_with_master.inc
SELECT @@GLOBAL.GTID_EXECUTED, @@GLOBAL.GTID_PURGED;
--let $rpl_server_number= 2
--source include/rpl_restart_server.inc
SELECT @@GLOBAL.GTID_EXECUTED, @@GLOBAL.GTID_PURGED;
Suggested fix:
=== modified file 'sql/rpl_gtid_state.cc'
--- sql/rpl_gtid_state.cc revid:sven.sandberg@oracle.com-20140924143530-f9esd9irj02s8jrm
+++ sql/rpl_gtid_state.cc 2014-10-08 15:56:35 +0000
@@ -149,27 +149,28 @@ void Gtid_state::update_on_commit(THD *t
global_sid_lock->rdlock();
if (!opt_bin_log || (thd->slave_thread && !opt_log_slave_updates))
{
- Gtid *gtid= &thd->owned_gtid;
-#ifndef DBUG_OFF
- lock_sidno(gtid->sidno);
- DBUG_ASSERT(!executed_gtids.contains_gtid(*gtid));
- unlock_sidno(gtid->sidno);
-#endif
+ Gtid >id= thd->owned_gtid;
/*
If binlog is disabled, any session adds transaction owned GTID
- into global executed_gtids.
+ into global executed_gtids and lost_gtids.
If binlog is enabled and log_slave_updates is disabled, slave
SQL thread or slave worker thread adds transaction owned GTID
into global executed_gtids and gtids_only_in_table.
*/
- lock_sidno(gtid->sidno);
+ lock_sidno(gtid.sidno);
+
+ DBUG_ASSERT(!executed_gtids.contains_gtid(gtid));
+
DBUG_EXECUTE_IF(
"rpl_gtid_update_on_commit_simulate_out_of_memory",
DBUG_SET("+d,rpl_gtid_get_free_interval_simulate_out_of_memory"););
- executed_gtids._add_gtid(*gtid);
+
+ executed_gtids._add_gtid(gtid);
+ lost_gtids._add_gtid(gtid);
if (thd->slave_thread && opt_bin_log && !opt_log_slave_updates)
- gtids_only_in_table._add_gtid(*gtid);
- unlock_sidno(gtid->sidno);
+ gtids_only_in_table._add_gtid(gtid);
+
+ unlock_sidno(gtid.sidno);
}
update_gtids_impl(thd, true);
Description: In 5.7, GTIDs can be enabled even if log-bin is not enabled or log-slave-updates is not enabled. In this case, when a transactions with a GTID is committed, the GTID is added to the table mysql.gtid_executed. Since 5.6, @@GLOBAL.GTID_PURGED contains the set of GTIDs which are included in @@GLOBAL.GTID_EXECUTED but not in the binary log. However, when a transaction is committed and the binary log is off, the GTID is not included in @@GLOBAL.GTID_PURGED. The GTID is added to @@GLOBAL.GTID_PURGED the next time the server restarts, since the procedure to read GTIDs from the binary log on server start is correct. But the GTID should be added to @@GLOBAL.GTID_PURGED already when the transaction is committed. How to repeat: --source include/have_gtid.inc --source include/master-slave.inc CREATE TABLE t1 (a INT); --source include/sync_slave_sql_with_master.inc SELECT @@GLOBAL.GTID_EXECUTED, @@GLOBAL.GTID_PURGED; --let $rpl_server_number= 2 --source include/rpl_restart_server.inc SELECT @@GLOBAL.GTID_EXECUTED, @@GLOBAL.GTID_PURGED; Suggested fix: === modified file 'sql/rpl_gtid_state.cc' --- sql/rpl_gtid_state.cc revid:sven.sandberg@oracle.com-20140924143530-f9esd9irj02s8jrm +++ sql/rpl_gtid_state.cc 2014-10-08 15:56:35 +0000 @@ -149,27 +149,28 @@ void Gtid_state::update_on_commit(THD *t global_sid_lock->rdlock(); if (!opt_bin_log || (thd->slave_thread && !opt_log_slave_updates)) { - Gtid *gtid= &thd->owned_gtid; -#ifndef DBUG_OFF - lock_sidno(gtid->sidno); - DBUG_ASSERT(!executed_gtids.contains_gtid(*gtid)); - unlock_sidno(gtid->sidno); -#endif + Gtid >id= thd->owned_gtid; /* If binlog is disabled, any session adds transaction owned GTID - into global executed_gtids. + into global executed_gtids and lost_gtids. If binlog is enabled and log_slave_updates is disabled, slave SQL thread or slave worker thread adds transaction owned GTID into global executed_gtids and gtids_only_in_table. */ - lock_sidno(gtid->sidno); + lock_sidno(gtid.sidno); + + DBUG_ASSERT(!executed_gtids.contains_gtid(gtid)); + DBUG_EXECUTE_IF( "rpl_gtid_update_on_commit_simulate_out_of_memory", DBUG_SET("+d,rpl_gtid_get_free_interval_simulate_out_of_memory");); - executed_gtids._add_gtid(*gtid); + + executed_gtids._add_gtid(gtid); + lost_gtids._add_gtid(gtid); if (thd->slave_thread && opt_bin_log && !opt_log_slave_updates) - gtids_only_in_table._add_gtid(*gtid); - unlock_sidno(gtid->sidno); + gtids_only_in_table._add_gtid(gtid); + + unlock_sidno(gtid.sidno); } update_gtids_impl(thd, true);