Skip to content

Commit c529846

Browse files
author
Sujatha Sivakumar
committed
Bug#16387720: BLOCKED WITH FLUSH TABLES WITH READ LOCK +
SHOW SLAVE STATUS Problem: ======= If a client thread on a slave does FLUSH TABLES WITH READ LOCK; then master does some updates, SHOW SLAVE STATUS in the same client will be blocked. If the blocked slave server is killed and restarted when GTID's are enabled, one GTID gets missed leaving the slave in an out of sync state. Using 'relay-log-recovery=1' should do a crash safe slave recovery but it is not happening. Analysis: ======== RPL info tables "slave_master_info" and "slave_relay_log_info" are used to store slave's thread's positions. When a FTWRL is issued on slave this command blocks all operations on tables. Hence when some update operations are done on master the slave thread will be able to open the tables but while closing, an internal commit operation will be blocked. These blocked info tables make the "SHOW SLAVE STATUS" to hang. When "relay-log-recovery=1" during crash recovery all the partial written events will be discarded the master info table is initialised with the information read from relay log info table. The "Retrieved GTID" set should be cleared so that partial read events are discarded and they are fetched once again. Since this is not happening "The Retried GTID" is considered to be executed and the actual transaction is skipped. Fix: === Info tables should be made independent of global read lock. At the time of opening the RPL info tables the following "MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK" flag is set to make the info tables not to block when the FTWRL is in progress. Hence a similar flag is introduced in "ha_commit_trans" code which will allow commit to complete even if a global read lock is active. This flag can be used to allow changes to internal tables (e.g. slave status tables). To fix the missing GTID issue using "relay-log-recovery" option, during recovery process retrieved GTID set is cleared.
1 parent 51baa21 commit c529846

6 files changed

Lines changed: 39 additions & 12 deletions

File tree

mysql-test/suite/rpl/t/rpl_check_gtid-slave.opt

Lines changed: 0 additions & 1 deletion
This file was deleted.

mysql-test/suite/rpl/t/rpl_check_gtid.test

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -788,10 +788,12 @@ while ($i != 5)
788788
--let $gtid_ini= 1
789789
--let $gtid_end= 1
790790
}
791+
# Post relay log recovery the previous GTIDs set should
792+
# be empty.
791793
if ($i != 1)
792794
{
793-
--let $gtid_set_ini= 1
794-
--let $gtid_set_end= `SELECT $i - 1`
795+
--let $gtid_set_ini= 0
796+
--let $gtid_set_end= 0
795797
--let $gtid_ini= `SELECT $i`
796798
--let $gtid_end= `SELECT $i`
797799
}
@@ -884,10 +886,12 @@ while ($i != 5)
884886
--let $gtid_ini= 1
885887
--let $gtid_end= 1
886888
}
889+
# Post relay log recovery the previous GTIDs set should
890+
# be empty.
887891
if ($i != 1)
888892
{
889-
--let $gtid_set_ini= 1
890-
--let $gtid_set_end= `SELECT $i - 1`
893+
--let $gtid_set_ini= 0
894+
--let $gtid_set_end= 0
891895
--let $gtid_ini= `SELECT $i`
892896
--let $gtid_end= `SELECT $i`
893897
}

sql/handler.cc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,11 @@ ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
12961296

12971297

12981298
/**
1299+
@param[in] ignore_global_read_lock Allow commit to complete even if a
1300+
global read lock is active. This can be
1301+
used to allow changes to internal tables
1302+
(e.g. slave status tables).
1303+
12991304
@retval
13001305
0 ok
13011306
@retval
@@ -1309,7 +1314,8 @@ ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
13091314
stored functions or triggers. So we simply do nothing now.
13101315
TODO: This should be fixed in later ( >= 5.1) releases.
13111316
*/
1312-
int ha_commit_trans(THD *thd, bool all)
1317+
1318+
int ha_commit_trans(THD *thd, bool all, bool ignore_global_read_lock)
13131319
{
13141320
int error= 0;
13151321
/*
@@ -1379,7 +1385,7 @@ int ha_commit_trans(THD *thd, bool all)
13791385
/* rw_trans is TRUE when we in a transaction changing data */
13801386
rw_trans= is_real_trans && (rw_ha_count > 0);
13811387

1382-
if (rw_trans)
1388+
if (rw_trans && !ignore_global_read_lock)
13831389
{
13841390
/*
13851391
Acquire a metadata lock which will ensure that COMMIT is blocked

sql/handler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3404,7 +3404,7 @@ int ha_release_temporary_latches(THD *thd);
34043404
/* transactions: interface to handlerton functions */
34053405
int ha_start_consistent_snapshot(THD *thd);
34063406
int ha_commit_or_rollback_by_xid(THD *thd, XID *xid, bool commit);
3407-
int ha_commit_trans(THD *thd, bool all);
3407+
int ha_commit_trans(THD *thd, bool all, bool ignore_global_read_lock= false);
34083408
int ha_rollback_trans(THD *thd, bool all);
34093409
int ha_prepare(THD *thd);
34103410
int ha_recover(HASH *commit_list);

sql/rpl_info_table_access.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -155,14 +155,25 @@ bool Rpl_info_table_access::close_table(THD *thd, TABLE* table,
155155
if (error)
156156
ha_rollback_trans(thd, FALSE);
157157
else
158-
ha_commit_trans(thd, FALSE);
159-
158+
{
159+
/*
160+
To make the commit not to block with global read lock set
161+
"ignore_global_read_lock" flag to true.
162+
*/
163+
ha_commit_trans(thd, FALSE, TRUE);
164+
}
160165
if (saved_current_thd != current_thd)
161166
{
162167
if (error)
163168
ha_rollback_trans(thd, TRUE);
164169
else
165-
ha_commit_trans(thd, TRUE);
170+
{
171+
/*
172+
To make the commit not to block with global read lock set
173+
"ignore_global_read_lock" flag to true.
174+
*/
175+
ha_commit_trans(thd, TRUE, TRUE);
176+
}
166177
}
167178
/*
168179
In order not to break execution of current statement we have to

sql/rpl_slave.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,13 @@ int init_recovery(Master_info* mi, const char** errmsg)
488488
rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);
489489
}
490490

491+
/*
492+
Clear the retrieved GTID set so that events that are written partially
493+
will be fetched again.
494+
*/
495+
global_sid_lock->wrlock();
496+
(const_cast<Gtid_set *>(rli->get_gtid_set()))->clear();
497+
global_sid_lock->unlock();
491498
DBUG_RETURN(error);
492499
}
493500

0 commit comments

Comments
 (0)