Merge lp:~akopytov/percona-server/backup_locks_bugs into lp:percona-server/5.6

Proposed by Alexey Kopytov
Status: Merged
Approved by: Laurynas Biveinis
Approved revision: no longer in the source branch.
Merged at revision: 663
Proposed branch: lp:~akopytov/percona-server/backup_locks_bugs
Merge into: lp:percona-server/5.6
Diff against target: 1000 lines (+487/-45)
16 files modified
mysql-test/suite/rpl/r/rpl_backup_locks.result (+7/-0)
mysql-test/suite/rpl/r/rpl_backup_locks_mts.result (+30/-0)
mysql-test/suite/rpl/r/rpl_bug1358836.result (+18/-0)
mysql-test/suite/rpl/t/rpl_backup_locks.test (+32/-0)
mysql-test/suite/rpl/t/rpl_backup_locks_mts-slave.opt (+1/-0)
mysql-test/suite/rpl/t/rpl_backup_locks_mts.test (+84/-0)
mysql-test/suite/rpl/t/rpl_bug1358836-slave.opt (+1/-0)
mysql-test/suite/rpl/t/rpl_bug1358836.test (+49/-0)
sql/binlog.cc (+13/-3)
sql/log_event.cc (+21/-0)
sql/rpl_info_factory.cc (+24/-0)
sql/rpl_rli.cc (+55/-21)
sql/rpl_rli.h (+17/-8)
sql/rpl_rli_pdb.cc (+56/-13)
sql/rpl_slave.cc (+77/-0)
sql/sql_class.h (+2/-0)
To merge this branch: bzr merge lp:~akopytov/percona-server/backup_locks_bugs
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Review via email: mp+235794@code.launchpad.net

Description of the change

Bug #1358836: Backup locks do not guarantee consistent SHOW SLAVE STATUS
              with binary log disabled

Bug #1372806: Deadlock with LOCK BINLOG FOR BACKUP + SHOW SLAVE STATUS
              with binary log enabled

The fixes are inter-dependent, hence a single revision for both bugs.

The problem in bug #1358836 was that with the binary log disabled slave
SQL threads did not acquire binlog protection locks when committing in
some cases. The original backup locks implementation was done in
assumption that the only place where master binary logs are updated is
Relay_log_info::inc_event_relay_log_pos(). Which is incorrect and
replication code does not make figuring things like these
easy. Relay_log_info::inc_event_relay_log_pos() is only called for
multi-statement transactions. There are different code paths for
AUTOCOMMIT transactions and other kinds of updates, depending on the
storage engines involved, event types, and whether the slave is
multi-threaded.

Inspecting all possible code paths was difficult, because Relay_log_info
members that have to be protected by an active BINLOG backup lock were
sometimes modified directly, rather than with the ‘setter’ functions,
i.e. set_group_master_log_name() and set_group_master_log_pos().

Fixed by:

- asserting that the current connection has acquired a binlog protection
lock in Relay_log_info::set_group_master_log_name() and
Relay_log_info::set_group_master_log_pos();

- changing all code that accessed those variables directly to use
getter/setter functions instead;

- making sure that whenever a setter function is called (i.e. master
binary log coordinates are updated), binlog protection is acquired;

- renaming the group_master_log_{name,pos} member variables of
Relay_log_info to m_group_master_log_{name,pos} to prevent other code
that modifies those variables directly from creeping in on future
changes or upstream merges;

The problem in bug #1372806 was that with binary log enabled, an SQL
thread would acquire a binlog protection lock after locking the
Relay_log_info::data_lock mutex, which resulted in a deadlock with a
user connection holding a binlog lock while executing SHOW SLAVE STATUS.

Fixed by inspecting the code and making sure that no binlog protection
locks are taken while the Relay_log_info::data_locks mutex is locked by
the same connection, and adding assertions where possible.

To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote :
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

    - Should Relay_log_info::purge_relay_logs set errmsg on failure to
      acquire binlog lock protection?

    - Why does Slave_worker::reset_recovery_info try to acquire the
      binlog protection and proceeds to call the setter without
      considering whether the acquisition succeeded? That will fail
      the DBUG_ASSERT in the setter in the case of failure at
      least. If I understand the context of the code correctly, it
      should be just like the other protection sites instead, with an
      early error return in the case of failure.

    - Have you considered extracting

bool rpl_acquire_backup_binlog_lock_protection(thd, rli)
{
  bool ret= true;
  if (thd && !thd->backup_binlog_lock.is_acquired())
  {
    const ulong timeout= info_thd->variables.lock_wait_timeout;

    DBUG_PRINT("debug", ("Acquiring binlog protection lock"));

    if (rli)
      mysql_mutex_assert_not_owner(&rli->data_lock);

   ret= !info_thd->backup_binlog_lock.acquire_protection(thd,
MDL_EXPLICIT, timeout);
  }
  return ret;
}

and void release(thd, bool protection_acquired)
{
  if (thd && prot_acquired)
  {
    DBUG_PRINT("debug", ("Releasing binlog protection lock"));
    thd->backup_binlog_lock.release_protection(thd);
  }
}

review: Needs Information
Revision history for this message
Alexey Kopytov (akopytov) wrote :

>
> - Should Relay_log_info::purge_relay_logs set errmsg on failure to
> acquire binlog lock protection?
>

No, because setting errmsg would cause callers to call
my_error(ER_RELAY_LOG_FAIL, errmsg), which is not what we want, because
that would have been already called by MDL_context::acquire_lock().

> - Why does Slave_worker::reset_recovery_info try to acquire the
> binlog protection and proceeds to call the setter without
> considering whether the acquisition succeeded? That will fail
> the DBUG_ASSERT in the setter in the case of failure at
> least. If I understand the context of the code correctly, it
> should be just like the other protection sites instead, with an
> early error return in the case of failure.
>

For some reasons I wasn’t sure if the callers are able to handle errors
returned by Slave_worker::reset_recovery_info(), but I can’t recall
them. Anyway, this seems to be a rather corner case, so I changed to
return an error instead.

> - Have you considered extracting
>
> bool rpl_acquire_backup_binlog_lock_protection(thd, rli)
> {
> bool ret= true;
> if (thd && !thd->backup_binlog_lock.is_acquired())
> {
> const ulong timeout= info_thd->variables.lock_wait_timeout;
>
> DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
>
> if (rli)
> mysql_mutex_assert_not_owner(&rli->data_lock);
>
> ret= !info_thd->backup_binlog_lock.acquire_protection(thd,
> MDL_EXPLICIT, timeout);
> }
> return ret;
> }
>
> and void release(thd, bool protection_acquired)
> {
> if (thd && prot_acquired)
> {
> DBUG_PRINT("debug", ("Releasing binlog protection lock"));
> thd->backup_binlog_lock.release_protection(thd);
> }
> }

I have, yes. That would prevent some code duplication, but not too much,
as callers would still have to handle errors, the ‘protection_acquired’
flag + some of them also assert that the current connection has not
acquired the binlog lock, while the others do not. Which means the
wrapper code around those acquire/release helper functions would be
about the same number of lines replicating to every site. So I decided
to leave it as is for clarity.

--
Best regards,
Alexey.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

OK if Jenkins OK

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'mysql-test/suite/rpl/r/rpl_backup_locks.result'
--- mysql-test/suite/rpl/r/rpl_backup_locks.result 2014-02-25 07:30:22 +0000
+++ mysql-test/suite/rpl/r/rpl_backup_locks.result 2014-09-24 16:59:42 +0000
@@ -29,6 +29,13 @@
29UNLOCK TABLES;29UNLOCK TABLES;
30include/check_slave_param.inc [Exec_Master_Log_Pos]30include/check_slave_param.inc [Exec_Master_Log_Pos]
31UNLOCK BINLOG;31UNLOCK BINLOG;
32# connection slave
33LOCK BINLOG FOR BACKUP;
34# connection master
35INSERT INTO t_innodb VALUES (1);
36# connection slave
37include/check_slave_param.inc [Exec_Master_Log_Pos]
38UNLOCK BINLOG;
32# connection master39# connection master
33DROP TABLE t_innodb, t_myisam;40DROP TABLE t_innodb, t_myisam;
34include/rpl_end.inc41include/rpl_end.inc
3542
=== added file 'mysql-test/suite/rpl/r/rpl_backup_locks_mts.result'
--- mysql-test/suite/rpl/r/rpl_backup_locks_mts.result 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/r/rpl_backup_locks_mts.result 2014-09-24 16:59:42 +0000
@@ -0,0 +1,30 @@
1include/master-slave.inc
2Warnings:
3Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5[connection master]
6CREATE DATABASE db_1;
7CREATE DATABASE db_2;
8CREATE TABLE db_1.test_1 (id INTEGER) engine=Innodb;
9CREATE TABLE db_2.test_1 (id INTEGER) engine=Innodb;
10include/sync_slave_sql_with_master.inc
11include/stop_slave.inc
12SET @save.slave_parallel_workers= @@GLOBAL.slave_parallel_workers;
13SET @@GLOBAL.slave_parallel_workers= 2;
14include/start_slave.inc
15LOCK BINLOG FOR BACKUP;
16INSERT INTO db_1.test_1 VALUES(1);
17INSERT INTO db_2.test_1 VALUES(1);
18include/check_slave_param.inc [Exec_Master_Log_Pos]
19UNLOCK BINLOG;
20include/sync_slave_sql_with_master.inc
21LOCK BINLOG FOR BACKUP;
22INSERT INTO db_1.test_1 VALUES(2);
23INSERT INTO db_2.test_1 VALUES(2);
24include/check_slave_param.inc [Exec_Master_Log_Pos]
25UNLOCK BINLOG;
26DROP DATABASE db_1;
27DROP DATABASE db_2;
28include/sync_slave_sql_with_master.inc
29SET @@GLOBAL.slave_parallel_workers= @save.slave_parallel_workers;
30include/rpl_end.inc
031
=== added file 'mysql-test/suite/rpl/r/rpl_bug1358836.result'
--- mysql-test/suite/rpl/r/rpl_bug1358836.result 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/r/rpl_bug1358836.result 2014-09-24 16:59:42 +0000
@@ -0,0 +1,18 @@
1include/master-slave.inc
2Warnings:
3Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5[connection master]
6CREATE TABLE t1 (
7a int(11) DEFAULT NULL
8) ENGINE=InnoDB DEFAULT CHARSET=latin1;
9# connection slave
10LOCK BINLOG FOR BACKUP;
11# connection master
12INSERT INTO t1 VALUES (1);
13# connection slave
14include/check_slave_param.inc [Exec_Master_Log_Pos]
15UNLOCK BINLOG;
16# connection master
17DROP TABLE t1;
18include/rpl_end.inc
019
=== modified file 'mysql-test/suite/rpl/t/rpl_backup_locks.test'
--- mysql-test/suite/rpl/t/rpl_backup_locks.test 2014-02-25 07:30:22 +0000
+++ mysql-test/suite/rpl/t/rpl_backup_locks.test 2014-09-24 16:59:42 +0000
@@ -86,6 +86,38 @@
8686
87UNLOCK BINLOG;87UNLOCK BINLOG;
8888
89############################################################################
90# Bug 1372806: Deadlock with LOCK BINLOG FOR BACKUP + SHOW SLAVE STATUS with
91# binary log enabled
92############################################################################
93
94--connection slave
95--echo # connection slave
96LOCK BINLOG FOR BACKUP;
97
98--let $master_log_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
99
100--connection master
101--echo # connection master
102INSERT INTO t_innodb VALUES (1);
103
104--connection slave
105--echo # connection slave
106let $wait_condition=
107 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
108 WHERE STATE = "Waiting for binlog lock" AND
109 (INFO = "INSERT INTO t_innodb VALUES (1)" OR INFO IS NULL);
110--source include/wait_condition.inc
111
112# The following would deadlock with binlog_format=stmt on SHOW SLAVE STATUS
113# before the fix
114
115--let $slave_param= Exec_Master_Log_Pos
116--let $slave_param_value= $master_log_pos
117--source include/check_slave_param.inc
118
119UNLOCK BINLOG;
120
89--connection master121--connection master
90--echo # connection master122--echo # connection master
91123
92124
=== added file 'mysql-test/suite/rpl/t/rpl_backup_locks_mts-slave.opt'
--- mysql-test/suite/rpl/t/rpl_backup_locks_mts-slave.opt 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/t/rpl_backup_locks_mts-slave.opt 2014-09-24 16:59:42 +0000
@@ -0,0 +1,1 @@
1--skip-log-bin --skip-log-slave-updates --slave-transaction-retries=0
02
=== added file 'mysql-test/suite/rpl/t/rpl_backup_locks_mts.test'
--- mysql-test/suite/rpl/t/rpl_backup_locks_mts.test 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/t/rpl_backup_locks_mts.test 2014-09-24 16:59:42 +0000
@@ -0,0 +1,84 @@
1###########################################################################
2# MTS tests for binlog backup locks
3###########################################################################
4
5--source include/have_innodb.inc
6--let $rpl_skip_reset_master_and_slave=1
7--source include/master-slave.inc
8
9--connection master
10CREATE DATABASE db_1;
11CREATE DATABASE db_2;
12
13CREATE TABLE db_1.test_1 (id INTEGER) engine=Innodb;
14CREATE TABLE db_2.test_1 (id INTEGER) engine=Innodb;
15
16--connection master
17--source include/sync_slave_sql_with_master.inc
18
19--connection slave
20
21--source include/stop_slave.inc
22
23SET @save.slave_parallel_workers= @@GLOBAL.slave_parallel_workers;
24SET @@GLOBAL.slave_parallel_workers= 2;
25
26--source include/start_slave.inc
27
28LOCK BINLOG FOR BACKUP;
29
30--let $master_log_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
31
32--connection master
33INSERT INTO db_1.test_1 VALUES(1);
34INSERT INTO db_2.test_1 VALUES(1);
35
36--connection slave
37
38let $wait_condition=
39 SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST
40 WHERE STATE = "Waiting for binlog lock" AND
41 (INFO LIKE "INSERT INTO db\__.test\__ VALUES(1))" OR INFO IS NULL);
42--source include/wait_condition.inc
43
44--let $slave_param= Exec_Master_Log_Pos
45--let $slave_param_value= $master_log_pos
46--source include/check_slave_param.inc
47
48UNLOCK BINLOG;
49
50--connection master
51--source include/sync_slave_sql_with_master.inc
52
53--connection slave
54LOCK BINLOG FOR BACKUP;
55
56--let $master_log_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
57
58--connection master
59INSERT INTO db_1.test_1 VALUES(2);
60INSERT INTO db_2.test_1 VALUES(2);
61
62--connection slave
63
64let $wait_condition=
65 SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST
66 WHERE STATE = "Waiting for binlog lock" AND
67 (INFO LIKE "INSERT INTO db\__.test\__ VALUES(2)" OR INFO IS NULL);
68--source include/wait_condition.inc
69
70--let $slave_param= Exec_Master_Log_Pos
71--let $slave_param_value= $master_log_pos
72--source include/check_slave_param.inc
73
74UNLOCK BINLOG;
75
76--connection master
77DROP DATABASE db_1;
78DROP DATABASE db_2;
79
80--source include/sync_slave_sql_with_master.inc
81
82SET @@GLOBAL.slave_parallel_workers= @save.slave_parallel_workers;
83
84--source include/rpl_end.inc
085
=== added file 'mysql-test/suite/rpl/t/rpl_bug1358836-slave.opt'
--- mysql-test/suite/rpl/t/rpl_bug1358836-slave.opt 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/t/rpl_bug1358836-slave.opt 2014-09-24 16:59:42 +0000
@@ -0,0 +1,1 @@
1--skip-log-bin --skip-log-slave-updates
02
=== added file 'mysql-test/suite/rpl/t/rpl_bug1358836.test'
--- mysql-test/suite/rpl/t/rpl_bug1358836.test 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/t/rpl_bug1358836.test 2014-09-24 16:59:42 +0000
@@ -0,0 +1,49 @@
1###############################################################################
2# Bug #1358836: Backup locks do not guarantee consistent SHOW SLAVE STATUS with
3# binary log disabled
4###############################################################################
5
6--source include/have_innodb.inc
7--let $rpl_skip_reset_master_and_slave=1
8--source include/master-slave.inc
9
10CREATE TABLE t1 (
11 a int(11) DEFAULT NULL
12) ENGINE=InnoDB DEFAULT CHARSET=latin1;
13
14sync_slave_with_master;
15
16--connection slave
17--echo # connection slave
18
19LOCK BINLOG FOR BACKUP;
20
21--let $master_log_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1)
22
23--connection master
24--echo # connection master
25
26INSERT INTO t1 VALUES (1);
27
28--connection slave
29--echo # connection slave
30
31let $wait_condition=
32 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
33 WHERE STATE = "Waiting for binlog lock" AND
34 (INFO = "INSERT INTO t1 VALUES (1)" OR INFO IS NULL);
35--source include/wait_condition.inc
36
37--let $slave_param= Exec_Master_Log_Pos
38--let $slave_param_value= $master_log_pos
39--source include/check_slave_param.inc
40
41UNLOCK BINLOG;
42
43--connection master
44--echo # connection master
45DROP TABLE t1;
46
47sync_slave_with_master;
48
49--source include/rpl_end.inc
050
=== modified file 'sql/binlog.cc'
--- sql/binlog.cc 2014-08-22 10:02:24 +0000
+++ sql/binlog.cc 2014-09-24 16:59:42 +0000
@@ -6446,6 +6446,7 @@
6446 my_xid xid= thd->transaction.xid_state.xid.get_my_xid();6446 my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
6447 int error= RESULT_SUCCESS;6447 int error= RESULT_SUCCESS;
6448 bool stuff_logged= false;6448 bool stuff_logged= false;
6449 bool binlog_prot_acquired= false;
64496450
6450 DBUG_PRINT("enter", ("thd: 0x%llx, all: %s, xid: %llu, cache_mngr: 0x%llx",6451 DBUG_PRINT("enter", ("thd: 0x%llx, all: %s, xid: %llu, cache_mngr: 0x%llx",
6451 (ulonglong) thd, YESNO(all), (ulonglong) xid,6452 (ulonglong) thd, YESNO(all), (ulonglong) xid,
@@ -6590,8 +6591,15 @@
6590 {6591 {
6591 int rc;6592 int rc;
65926593
6593 /* Block binlog updates if there's an active BINLOG lock. */6594 /*
6594 if (!thd->backup_binlog_lock.is_acquired())6595 Block binlog updates if there's an active BINLOG lock.
6596
6597 We allow binlog lock owner to commit, assuming it knows what it does. We
6598 also check if protection has not been acquired earlier, which is possible
6599 in slave threads to protect master binlog coordinates.
6600 */
6601 if (!thd->backup_binlog_lock.is_acquired() &&
6602 !thd->backup_binlog_lock.is_protection_acquired())
6595 {6603 {
6596 const ulong timeout= thd->variables.lock_wait_timeout;6604 const ulong timeout= thd->variables.lock_wait_timeout;
65976605
@@ -6604,11 +6612,13 @@
66046612
6605 DBUG_RETURN(RESULT_ABORTED);6613 DBUG_RETURN(RESULT_ABORTED);
6606 }6614 }
6615
6616 binlog_prot_acquired= true;
6607 }6617 }
66086618
6609 rc= ordered_commit(thd, all);6619 rc= ordered_commit(thd, all);
66106620
6611 if (!thd->backup_binlog_lock.is_acquired())6621 if (binlog_prot_acquired)
6612 {6622 {
6613 DBUG_PRINT("debug", ("Releasing binlog protection lock"));6623 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
6614 thd->backup_binlog_lock.release_protection(thd);6624 thd->backup_binlog_lock.release_protection(thd);
66156625
=== modified file 'sql/log_event.cc'
--- sql/log_event.cc 2014-08-22 10:02:24 +0000
+++ sql/log_event.cc 2014-09-24 16:59:42 +0000
@@ -6910,6 +6910,7 @@
6910 */6910 */
6911 DBUG_ASSERT(!thd->backup_binlog_lock.is_acquired());6911 DBUG_ASSERT(!thd->backup_binlog_lock.is_acquired());
6912 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));6912 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
6913 mysql_mutex_assert_not_owner(&rli->data_lock);
6913 const ulong timeout= thd->variables.lock_wait_timeout;6914 const ulong timeout= thd->variables.lock_wait_timeout;
6914 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT, timeout))6915 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT, timeout))
6915 {6916 {
@@ -7431,11 +7432,25 @@
7431 lex_start(thd);7432 lex_start(thd);
7432 mysql_reset_thd_for_next_command(thd);7433 mysql_reset_thd_for_next_command(thd);
7433 Relay_log_info *rli_ptr= const_cast<Relay_log_info *>(rli);7434 Relay_log_info *rli_ptr= const_cast<Relay_log_info *>(rli);
7435 bool binlog_prot_acquired= false;
74347436
7435 /* For a slave Xid_log_event is COMMIT */7437 /* For a slave Xid_log_event is COMMIT */
7436 general_log_print(thd, COM_QUERY,7438 general_log_print(thd, COM_QUERY,
7437 "COMMIT /* implicit, from Xid_log_event */");7439 "COMMIT /* implicit, from Xid_log_event */");
74387440
7441 if (!thd->backup_binlog_lock.is_acquired())
7442 {
7443 const ulong timeout= thd->variables.lock_wait_timeout;
7444
7445 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
7446 mysql_mutex_assert_not_owner(&rli->data_lock);
7447 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
7448 timeout))
7449 return 1;
7450
7451 binlog_prot_acquired= true;
7452 }
7453
7439 mysql_mutex_lock(&rli_ptr->data_lock);7454 mysql_mutex_lock(&rli_ptr->data_lock);
74407455
7441 DBUG_PRINT("info", ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",7456 DBUG_PRINT("info", ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
@@ -7496,6 +7511,12 @@
7496 mysql_cond_broadcast(&rli_ptr->data_cond);7511 mysql_cond_broadcast(&rli_ptr->data_cond);
7497 mysql_mutex_unlock(&rli_ptr->data_lock);7512 mysql_mutex_unlock(&rli_ptr->data_lock);
74987513
7514 if (binlog_prot_acquired)
7515 {
7516 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
7517 thd->backup_binlog_lock.release_protection(thd);
7518 }
7519
7499 return error;7520 return error;
7500}7521}
75017522
75027523
=== modified file 'sql/rpl_info_factory.cc'
--- sql/rpl_info_factory.cc 2013-10-15 11:37:57 +0000
+++ sql/rpl_info_factory.cc 2014-09-24 16:59:42 +0000
@@ -529,6 +529,8 @@
529 bool error= true;529 bool error= true;
530 enum_return_check return_check_src= ERROR_CHECKING_REPOSITORY;530 enum_return_check return_check_src= ERROR_CHECKING_REPOSITORY;
531 enum_return_check return_check_dst= ERROR_CHECKING_REPOSITORY;531 enum_return_check return_check_dst= ERROR_CHECKING_REPOSITORY;
532 bool binlog_prot_acquired= false;
533 THD * const thd= current_thd;
532 DBUG_ENTER("Rpl_info_factory::decide_repository");534 DBUG_ENTER("Rpl_info_factory::decide_repository");
533535
534 if (option == INFO_REPOSITORY_DUMMY)536 if (option == INFO_REPOSITORY_DUMMY)
@@ -585,6 +587,23 @@
585 goto err;587 goto err;
586588
587 /*589 /*
590 Acquire a backup binlog protection lock, because Rpl_info::copy_info()
591 will modify master binary log coordinates.
592 */
593 if (thd && !thd->backup_binlog_lock.is_acquired())
594 {
595 const ulong timeout= thd->variables.lock_wait_timeout;
596
597 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
598
599 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
600 timeout))
601 goto err;
602
603 binlog_prot_acquired= true;
604 }
605
606 /*
588 Transfer information from source to destination and delete the607 Transfer information from source to destination and delete the
589 source. Note this is not fault-tolerant and a crash before removing608 source. Note this is not fault-tolerant and a crash before removing
590 source may cause the next restart to fail as is_src and is_dest may609 source may cause the next restart to fail as is_src and is_dest may
@@ -628,6 +647,11 @@
628 }647 }
629648
630err:649err:
650 if (binlog_prot_acquired)
651 {
652 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
653 thd->backup_binlog_lock.release_protection(thd);
654 }
631 DBUG_RETURN(error); 655 DBUG_RETURN(error);
632}656}
633657
634658
=== modified file 'sql/rpl_rli.cc'
--- sql/rpl_rli.cc 2014-02-27 12:29:47 +0000
+++ sql/rpl_rli.cc 2014-09-24 16:59:42 +0000
@@ -78,7 +78,7 @@
78 is_relay_log_recovery(is_slave_recovery),78 is_relay_log_recovery(is_slave_recovery),
79 save_temporary_tables(0),79 save_temporary_tables(0),
80 cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),80 cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),
81 group_master_log_pos(0),81 m_group_master_log_pos(0),
82 gtid_set(global_sid_map, global_sid_lock),82 gtid_set(global_sid_map, global_sid_lock),
83 log_space_total(0), ignore_log_space_limit(0),83 log_space_total(0), ignore_log_space_limit(0),
84 sql_force_rotate_relay(false),84 sql_force_rotate_relay(false),
@@ -120,7 +120,7 @@
120#endif120#endif
121121
122 group_relay_log_name[0]= event_relay_log_name[0]=122 group_relay_log_name[0]= event_relay_log_name[0]=
123 group_master_log_name[0]= 0;123 m_group_master_log_name[0]= 0;
124 until_log_name[0]= ign_master_log_name_end[0]= 0;124 until_log_name[0]= ign_master_log_name_end[0]= 0;
125 set_timespec_nsec(last_clock, 0);125 set_timespec_nsec(last_clock, 0);
126 memset(&cache_buf, 0, sizeof(cache_buf));126 memset(&cache_buf, 0, sizeof(cache_buf));
@@ -688,6 +688,8 @@
688 {688 {
689 bool pos_reached;689 bool pos_reached;
690 int cmp_result= 0;690 int cmp_result= 0;
691 const char * const group_master_log_name= get_group_master_log_name();
692 const ulonglong group_master_log_pos= get_group_master_log_pos();
691693
692 DBUG_PRINT("info",694 DBUG_PRINT("info",
693 ("init_abort_pos_wait: %ld abort_pos_wait: %ld",695 ("init_abort_pos_wait: %ld abort_pos_wait: %ld",
@@ -710,8 +712,8 @@
710 */712 */
711 if (*group_master_log_name)713 if (*group_master_log_name)
712 {714 {
713 char *basename= (group_master_log_name +715 const char * const basename= (group_master_log_name +
714 dirname_length(group_master_log_name));716 dirname_length(group_master_log_name));
715 /*717 /*
716 First compare the parts before the extension.718 First compare the parts before the extension.
717 Find the dot in the master's log basename,719 Find the dot in the master's log basename,
@@ -962,6 +964,7 @@
962 */964 */
963 DBUG_ASSERT(!info_thd->backup_binlog_lock.is_acquired());965 DBUG_ASSERT(!info_thd->backup_binlog_lock.is_acquired());
964 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));966 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
967 mysql_mutex_assert_not_owner(&data_lock);
965 if (info_thd->backup_binlog_lock.acquire_protection(info_thd, MDL_EXPLICIT,968 if (info_thd->backup_binlog_lock.acquire_protection(info_thd, MDL_EXPLICIT,
966 timeout))969 timeout))
967 DBUG_RETURN(1);970 DBUG_RETURN(1);
@@ -971,8 +974,7 @@
971 else974 else
972 {975 {
973 mysql_mutex_assert_owner(&data_lock);976 mysql_mutex_assert_owner(&data_lock);
974 DBUG_ASSERT(info_thd->mdl_context.is_lock_owner(MDL_key::BINLOG, "", "",977 DBUG_ASSERT(info_thd->backup_binlog_lock.is_protection_acquired());
975 MDL_INTENTION_EXCLUSIVE));
976 }978 }
977979
978 inc_event_relay_log_pos();980 inc_event_relay_log_pos();
@@ -1003,10 +1005,10 @@
1003 With the end_log_pos solution, we avoid computations involving lengthes.1005 With the end_log_pos solution, we avoid computations involving lengthes.
1004 */1006 */
1005 DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",1007 DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
1006 (long) log_pos, (long) group_master_log_pos));1008 (long) log_pos, (long) get_group_master_log_pos()));
10071009
1008 if (log_pos > 0) // 3.23 binlogs don't have log_posx1010 if (log_pos > 0) // 3.23 binlogs don't have log_posx
1009 group_master_log_pos= log_pos;1011 set_group_master_log_pos(log_pos);
10101012
1011 /*1013 /*
1012 In MTS mode FD or Rotate event commit their solitary group to1014 In MTS mode FD or Rotate event commit their solitary group to
@@ -1080,6 +1082,7 @@
1080{1082{
1081 int error=0;1083 int error=0;
1082 DBUG_ENTER("Relay_log_info::purge_relay_logs");1084 DBUG_ENTER("Relay_log_info::purge_relay_logs");
1085 bool binlog_prot_acquired= false;
10831086
1084 /*1087 /*
1085 Even if inited==0, we still try to empty master_log_* variables. Indeed,1088 Even if inited==0, we still try to empty master_log_* variables. Indeed,
@@ -1097,12 +1100,33 @@
1097 SLAVE, he will see old, confusing master_log_*. In other words, we reinit1100 SLAVE, he will see old, confusing master_log_*. In other words, we reinit
1098 master_log_* for SHOW SLAVE STATUS to display fine in any case.1101 master_log_* for SHOW SLAVE STATUS to display fine in any case.
1099 */1102 */
1100 group_master_log_name[0]= 0;1103
1101 group_master_log_pos= 0;1104 if (!thd->backup_binlog_lock.is_acquired())
1105 {
1106 const ulong timeout= thd->variables.lock_wait_timeout;
1107
1108 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
1109 mysql_mutex_assert_not_owner(&data_lock);
1110 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
1111 timeout))
1112 return 1;
1113
1114 binlog_prot_acquired= true;
1115 }
1116
1117 set_group_master_log_name("");
1118 set_group_master_log_pos(0);
11021119
1103 if (!inited)1120 if (!inited)
1104 {1121 {
1105 DBUG_PRINT("info", ("inited == 0"));1122 DBUG_PRINT("info", ("inited == 0"));
1123
1124 if (binlog_prot_acquired)
1125 {
1126 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
1127 thd->backup_binlog_lock.release_protection(thd);
1128 }
1129
1106 DBUG_RETURN(0);1130 DBUG_RETURN(0);
1107 }1131 }
11081132
@@ -1154,6 +1178,13 @@
1154#endif1178#endif
1155 DBUG_PRINT("info",("log_space_total: %s",llstr(log_space_total,buf)));1179 DBUG_PRINT("info",("log_space_total: %s",llstr(log_space_total,buf)));
1156 mysql_mutex_unlock(&data_lock);1180 mysql_mutex_unlock(&data_lock);
1181
1182 if (binlog_prot_acquired)
1183 {
1184 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
1185 thd->backup_binlog_lock.release_protection(thd);
1186 }
1187
1157 DBUG_RETURN(error);1188 DBUG_RETURN(error);
1158}1189}
11591190
@@ -1206,10 +1237,10 @@
1206 {1237 {
1207 if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id)1238 if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id)
1208 DBUG_RETURN(false);1239 DBUG_RETURN(false);
1209 log_name= group_master_log_name;1240 log_name= get_group_master_log_name();
1210 log_pos= (!ev)? group_master_log_pos :1241 log_pos= (!ev) ? get_group_master_log_pos() :
1211 ((thd->variables.option_bits & OPTION_BEGIN || !ev->log_pos) ?1242 ((thd->variables.option_bits & OPTION_BEGIN || !ev->log_pos) ?
1212 group_master_log_pos : ev->log_pos - ev->data_written);1243 get_group_master_log_pos() : ev->log_pos - ev->data_written);
1213 }1244 }
1214 else1245 else
1215 { /* until_condition == UNTIL_RELAY_POS */1246 { /* until_condition == UNTIL_RELAY_POS */
@@ -1221,7 +1252,8 @@
1221 {1252 {
1222 char buf[32];1253 char buf[32];
1223 DBUG_PRINT("info", ("group_master_log_name='%s', group_master_log_pos=%s",1254 DBUG_PRINT("info", ("group_master_log_name='%s', group_master_log_pos=%s",
1224 group_master_log_name, llstr(group_master_log_pos, buf)));1255 get_group_master_log_name(),
1256 llstr(get_group_master_log_pos(), buf)));
1225 DBUG_PRINT("info", ("group_relay_log_name='%s', group_relay_log_pos=%s",1257 DBUG_PRINT("info", ("group_relay_log_name='%s', group_relay_log_pos=%s",
1226 group_relay_log_name, llstr(group_relay_log_pos, buf)));1258 group_relay_log_name, llstr(group_relay_log_pos, buf)));
1227 DBUG_PRINT("info", ("(%s) log_name='%s', log_pos=%s",1259 DBUG_PRINT("info", ("(%s) log_name='%s', log_pos=%s",
@@ -1857,8 +1889,8 @@
1857 error= 1;1889 error= 1;
1858 goto err;1890 goto err;
1859 }1891 }
1860 group_master_log_name[0]= 0;1892 set_group_master_log_name("");
1861 group_master_log_pos= 0;1893 set_group_master_log_pos(0);
1862 }1894 }
1863 else1895 else
1864 {1896 {
@@ -2069,6 +2101,7 @@
2069 int lines= 0;2101 int lines= 0;
2070 char *first_non_digit= NULL;2102 char *first_non_digit= NULL;
2071 ulong temp_group_relay_log_pos= 0;2103 ulong temp_group_relay_log_pos= 0;
2104 char temp_group_master_log_name[FN_REFLEN];
2072 ulong temp_group_master_log_pos= 0;2105 ulong temp_group_master_log_pos= 0;
2073 int temp_sql_delay= 0;2106 int temp_sql_delay= 0;
2074 int temp_internal_id= internal_id;2107 int temp_internal_id= internal_id;
@@ -2133,8 +2166,8 @@
21332166
2134 if (from->get_info((ulong *) &temp_group_relay_log_pos,2167 if (from->get_info((ulong *) &temp_group_relay_log_pos,
2135 (ulong) BIN_LOG_HEADER_SIZE) ||2168 (ulong) BIN_LOG_HEADER_SIZE) ||
2136 from->get_info(group_master_log_name,2169 from->get_info(temp_group_master_log_name,
2137 (size_t) sizeof(group_relay_log_name),2170 (size_t) sizeof(temp_group_master_log_name),
2138 (char *) "") ||2171 (char *) "") ||
2139 from->get_info((ulong *) &temp_group_master_log_pos,2172 from->get_info((ulong *) &temp_group_master_log_pos,
2140 (ulong) 0))2173 (ulong) 0))
@@ -2159,7 +2192,8 @@
2159 }2192 }
2160 2193
2161 group_relay_log_pos= temp_group_relay_log_pos;2194 group_relay_log_pos= temp_group_relay_log_pos;
2162 group_master_log_pos= temp_group_master_log_pos;2195 set_group_master_log_name(temp_group_master_log_name);
2196 set_group_master_log_pos(temp_group_master_log_pos);
2163 sql_delay= (int32) temp_sql_delay;2197 sql_delay= (int32) temp_sql_delay;
2164 internal_id= (uint) temp_internal_id;2198 internal_id= (uint) temp_internal_id;
21652199
@@ -2182,8 +2216,8 @@
2182 to->set_info((int) LINES_IN_RELAY_LOG_INFO_WITH_ID) ||2216 to->set_info((int) LINES_IN_RELAY_LOG_INFO_WITH_ID) ||
2183 to->set_info(group_relay_log_name) ||2217 to->set_info(group_relay_log_name) ||
2184 to->set_info((ulong) group_relay_log_pos) ||2218 to->set_info((ulong) group_relay_log_pos) ||
2185 to->set_info(group_master_log_name) ||2219 to->set_info(get_group_master_log_name()) ||
2186 to->set_info((ulong) group_master_log_pos) ||2220 to->set_info((ulong) get_group_master_log_pos()) ||
2187 to->set_info((int) sql_delay) ||2221 to->set_info((int) sql_delay) ||
2188 to->set_info(recovery_parallel_workers) ||2222 to->set_info(recovery_parallel_workers) ||
2189 to->set_info((int) internal_id))2223 to->set_info((int) internal_id))
21902224
=== modified file 'sql/rpl_rli.h'
--- sql/rpl_rli.h 2014-06-04 14:48:06 +0000
+++ sql/rpl_rli.h 2014-09-24 16:59:42 +0000
@@ -223,8 +223,8 @@
223 !belongs_to_client(); client thread executing BINLOG statement if223 !belongs_to_client(); client thread executing BINLOG statement if
224 belongs_to_client()).224 belongs_to_client()).
225 */225 */
226 char group_master_log_name[FN_REFLEN];226 char m_group_master_log_name[FN_REFLEN];
227 volatile my_off_t group_master_log_pos;227 volatile my_off_t m_group_master_log_pos;
228228
229 /*229 /*
230 When it commits, InnoDB internally stores the master log position it has230 When it commits, InnoDB internally stores the master log position it has
@@ -417,7 +417,7 @@
417 bool is_until_satisfied(THD *thd, Log_event *ev);417 bool is_until_satisfied(THD *thd, Log_event *ev);
418 inline ulonglong until_pos()418 inline ulonglong until_pos()
419 {419 {
420 return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :420 return ((until_condition == UNTIL_MASTER_POS) ? get_group_master_log_pos() :
421 group_relay_log_pos);421 group_relay_log_pos);
422 }422 }
423423
@@ -733,15 +733,24 @@
733 future_event_relay_log_pos= log_pos;733 future_event_relay_log_pos= log_pos;
734 }734 }
735735
736 inline const char* get_group_master_log_name() { return group_master_log_name; }736 inline const char* get_group_master_log_name()
737 inline ulonglong get_group_master_log_pos() { return group_master_log_pos; }737 {
738 return m_group_master_log_name;
739 }
740 inline ulonglong get_group_master_log_pos() { return m_group_master_log_pos; }
738 inline void set_group_master_log_name(const char *log_file_name)741 inline void set_group_master_log_name(const char *log_file_name)
739 {742 {
740 strmake(group_master_log_name,log_file_name, sizeof(group_master_log_name)-1);743 DBUG_ASSERT(!info_thd ||
744 info_thd->backup_binlog_lock.is_protection_acquired());
745
746 strmake(m_group_master_log_name, log_file_name,
747 sizeof(m_group_master_log_name) - 1);
741 }748 }
742 inline void set_group_master_log_pos(ulonglong log_pos)749 inline void set_group_master_log_pos(ulonglong log_pos)
743 {750 {
744 group_master_log_pos= log_pos;751 DBUG_ASSERT(!info_thd ||
752 info_thd->backup_binlog_lock.is_protection_acquired());
753 m_group_master_log_pos= log_pos;
745 }754 }
746755
747 inline const char* get_group_relay_log_name() { return group_relay_log_name; }756 inline const char* get_group_relay_log_name() { return group_relay_log_name; }
@@ -775,7 +784,7 @@
775 }784 }
776 inline const char* get_rpl_log_name()785 inline const char* get_rpl_log_name()
777 {786 {
778 return (group_master_log_name[0] ? group_master_log_name : "FIRST");787 return (m_group_master_log_name[0] ? m_group_master_log_name : "FIRST");
779 }788 }
780789
781#if MYSQL_VERSION_ID < 40100790#if MYSQL_VERSION_ID < 40100
782791
=== modified file 'sql/rpl_rli_pdb.cc'
--- sql/rpl_rli_pdb.cc 2014-08-22 10:02:24 +0000
+++ sql/rpl_rli_pdb.cc 2014-09-24 16:59:42 +0000
@@ -300,6 +300,7 @@
300 DBUG_ENTER("Slave_worker::read_info");300 DBUG_ENTER("Slave_worker::read_info");
301301
302 ulong temp_group_relay_log_pos= 0;302 ulong temp_group_relay_log_pos= 0;
303 char temp_group_master_log_name[FN_REFLEN];
303 ulong temp_group_master_log_pos= 0;304 ulong temp_group_master_log_pos= 0;
304 ulong temp_checkpoint_relay_log_pos= 0;305 ulong temp_checkpoint_relay_log_pos= 0;
305 ulong temp_checkpoint_master_log_pos= 0;306 ulong temp_checkpoint_master_log_pos= 0;
@@ -317,8 +318,8 @@
317 (char *) "") ||318 (char *) "") ||
318 from->get_info((ulong *) &temp_group_relay_log_pos,319 from->get_info((ulong *) &temp_group_relay_log_pos,
319 (ulong) 0) ||320 (ulong) 0) ||
320 from->get_info(group_master_log_name,321 from->get_info(temp_group_master_log_name,
321 (size_t) sizeof(group_master_log_name),322 (size_t) sizeof(temp_group_master_log_name),
322 (char *) "") ||323 (char *) "") ||
323 from->get_info((ulong *) &temp_group_master_log_pos,324 from->get_info((ulong *) &temp_group_master_log_pos,
324 (ulong) 0) ||325 (ulong) 0) ||
@@ -343,7 +344,8 @@
343344
344 internal_id=(uint) temp_internal_id;345 internal_id=(uint) temp_internal_id;
345 group_relay_log_pos= temp_group_relay_log_pos;346 group_relay_log_pos= temp_group_relay_log_pos;
346 group_master_log_pos= temp_group_master_log_pos;347 set_group_master_log_name(temp_group_master_log_name);
348 set_group_master_log_pos(temp_group_master_log_pos);
347 checkpoint_relay_log_pos= temp_checkpoint_relay_log_pos;349 checkpoint_relay_log_pos= temp_checkpoint_relay_log_pos;
348 checkpoint_master_log_pos= temp_checkpoint_master_log_pos;350 checkpoint_master_log_pos= temp_checkpoint_master_log_pos;
349 checkpoint_seqno= temp_checkpoint_seqno;351 checkpoint_seqno= temp_checkpoint_seqno;
@@ -363,8 +365,8 @@
363 to->set_info((int) internal_id) ||365 to->set_info((int) internal_id) ||
364 to->set_info(group_relay_log_name) ||366 to->set_info(group_relay_log_name) ||
365 to->set_info((ulong) group_relay_log_pos) ||367 to->set_info((ulong) group_relay_log_pos) ||
366 to->set_info(group_master_log_name) ||368 to->set_info(get_group_master_log_name()) ||
367 to->set_info((ulong) group_master_log_pos) ||369 to->set_info((ulong) get_group_master_log_pos()) ||
368 to->set_info(checkpoint_relay_log_name) ||370 to->set_info(checkpoint_relay_log_name) ||
369 to->set_info((ulong) checkpoint_relay_log_pos) ||371 to->set_info((ulong) checkpoint_relay_log_pos) ||
370 to->set_info(checkpoint_master_log_name) ||372 to->set_info(checkpoint_master_log_name) ||
@@ -387,11 +389,33 @@
387*/389*/
388bool Slave_worker::reset_recovery_info()390bool Slave_worker::reset_recovery_info()
389{391{
392 bool binlog_prot_acquired= false;
393
390 DBUG_ENTER("Slave_worker::reset_recovery_info");394 DBUG_ENTER("Slave_worker::reset_recovery_info");
391395
396 if (info_thd && !info_thd->backup_binlog_lock.is_acquired())
397 {
398 const ulong timeout= info_thd->variables.lock_wait_timeout;
399
400 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
401
402 if (info_thd->backup_binlog_lock.acquire_protection(info_thd, MDL_EXPLICIT,
403 timeout))
404 DBUG_RETURN(true);
405
406 binlog_prot_acquired= true;
407 }
408
392 set_group_master_log_name("");409 set_group_master_log_name("");
393 set_group_master_log_pos(0);410 set_group_master_log_pos(0);
394411
412 if (binlog_prot_acquired)
413 {
414 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
415 info_thd->backup_binlog_lock.release_protection(info_thd);
416 }
417
418
395 DBUG_RETURN(flush_info(true));419 DBUG_RETURN(flush_info(true));
396}420}
397421
@@ -410,8 +434,22 @@
410434
411bool Slave_worker::commit_positions(Log_event *ev, Slave_job_group* ptr_g, bool force)435bool Slave_worker::commit_positions(Log_event *ev, Slave_job_group* ptr_g, bool force)
412{436{
437 bool binlog_prot_acquired= false;
413 DBUG_ENTER("Slave_worker::checkpoint_positions");438 DBUG_ENTER("Slave_worker::checkpoint_positions");
414439
440 if (info_thd && !info_thd->backup_binlog_lock.is_acquired())
441 {
442 const ulong timeout= info_thd->variables.lock_wait_timeout;
443
444 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
445
446 if (info_thd->backup_binlog_lock.acquire_protection(info_thd, MDL_EXPLICIT,
447 timeout))
448 DBUG_RETURN(true);
449
450 binlog_prot_acquired= true;
451 }
452
415 /*453 /*
416 Initial value of checkpoint_master_log_name is learned from454 Initial value of checkpoint_master_log_name is learned from
417 group_master_log_name. The latter can be passed to Worker455 group_master_log_name. The latter can be passed to Worker
@@ -422,11 +460,10 @@
422 */460 */
423 if (ptr_g->group_master_log_name != NULL)461 if (ptr_g->group_master_log_name != NULL)
424 {462 {
425 strmake(group_master_log_name, ptr_g->group_master_log_name,463 set_group_master_log_name(ptr_g->group_master_log_name);
426 sizeof(group_master_log_name) - 1);
427 my_free(ptr_g->group_master_log_name);464 my_free(ptr_g->group_master_log_name);
428 ptr_g->group_master_log_name= NULL;465 ptr_g->group_master_log_name= NULL;
429 strmake(checkpoint_master_log_name, group_master_log_name,466 strmake(checkpoint_master_log_name, get_group_master_log_name(),
430 sizeof(checkpoint_master_log_name) - 1);467 sizeof(checkpoint_master_log_name) - 1);
431 }468 }
432 if (ptr_g->checkpoint_log_name != NULL)469 if (ptr_g->checkpoint_log_name != NULL)
@@ -467,19 +504,19 @@
467 bitmap_set_bit(&group_executed, ptr_g->checkpoint_seqno);504 bitmap_set_bit(&group_executed, ptr_g->checkpoint_seqno);
468 checkpoint_seqno= ptr_g->checkpoint_seqno;505 checkpoint_seqno= ptr_g->checkpoint_seqno;
469 group_relay_log_pos= ev->future_event_relay_log_pos;506 group_relay_log_pos= ev->future_event_relay_log_pos;
470 group_master_log_pos= ev->log_pos;507 set_group_master_log_pos(ev->log_pos);
471508
472 /*509 /*
473 Directly accessing c_rli->get_group_master_log_name() does not510 Directly accessing c_rli->get_group_master_log_name() does not
474 represent a concurrency issue because the current code places511 represent a concurrency issue because the current code places
475 a synchronization point when master rotates.512 a synchronization point when master rotates.
476 */513 */
477 strmake(group_master_log_name, c_rli->get_group_master_log_name(),514 set_group_master_log_name(c_rli->get_group_master_log_name());
478 sizeof(group_master_log_name)-1);
479515
480 DBUG_PRINT("mts", ("Committing worker-id %lu group master log pos %llu "516 DBUG_PRINT("mts", ("Committing worker-id %lu group master log pos %llu "
481 "group master log name %s checkpoint sequence number %lu.",517 "group master log name %s checkpoint sequence number %lu.",
482 id, group_master_log_pos, group_master_log_name, checkpoint_seqno));518 id, get_group_master_log_pos(),
519 get_group_master_log_name(), checkpoint_seqno));
483520
484 DBUG_EXECUTE_IF("mts_debug_concurrent_access",521 DBUG_EXECUTE_IF("mts_debug_concurrent_access",
485 {522 {
@@ -487,6 +524,12 @@
487 };524 };
488 );525 );
489526
527 if (binlog_prot_acquired)
528 {
529 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
530 info_thd->backup_binlog_lock.release_protection(info_thd);
531 }
532
490 DBUG_RETURN(flush_info(force));533 DBUG_RETURN(flush_info(force));
491}534}
492535
@@ -1060,7 +1103,7 @@
1060 );1103 );
1061 }1104 }
10621105
1063 ptr_g->group_master_log_pos= group_master_log_pos;1106 ptr_g->group_master_log_pos= get_group_master_log_pos();
1064 ptr_g->group_relay_log_pos= group_relay_log_pos;1107 ptr_g->group_relay_log_pos= group_relay_log_pos;
10651108
1066 ptr_g->done= 1; // GAQ index is available to C now1109 ptr_g->done= 1; // GAQ index is available to C now
10671110
=== modified file 'sql/rpl_slave.cc'
--- sql/rpl_slave.cc 2014-08-22 10:02:24 +0000
+++ sql/rpl_slave.cc 2014-09-24 16:59:42 +0000
@@ -507,6 +507,21 @@
507 int init_error= 0;507 int init_error= 0;
508 enum_return_check check_return= ERROR_CHECKING_REPOSITORY;508 enum_return_check check_return= ERROR_CHECKING_REPOSITORY;
509 THD *thd= current_thd;509 THD *thd= current_thd;
510 bool binlog_prot_acquired= false;
511
512 if (thd && !thd->backup_binlog_lock.is_acquired())
513 {
514 const ulong timeout= thd->variables.lock_wait_timeout;
515
516 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
517 mysql_mutex_assert_not_owner(&mi->rli->data_lock);
518
519 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
520 timeout))
521 DBUG_RETURN(1);
522
523 binlog_prot_acquired= true;
524 }
510525
511 /*526 /*
512 We need a mutex while we are changing master info parameters to527 We need a mutex while we are changing master info parameters to
@@ -570,6 +585,13 @@
570585
571 mysql_mutex_unlock(&mi->rli->data_lock);586 mysql_mutex_unlock(&mi->rli->data_lock);
572 mysql_mutex_unlock(&mi->data_lock);587 mysql_mutex_unlock(&mi->data_lock);
588
589 if (binlog_prot_acquired)
590 {
591 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
592 thd->backup_binlog_lock.release_protection(thd);
593 }
594
573 DBUG_RETURN(check_return == ERROR_CHECKING_REPOSITORY || init_error);595 DBUG_RETURN(check_return == ERROR_CHECKING_REPOSITORY || init_error);
574}596}
575597
@@ -5066,6 +5088,7 @@
5066 ulong cnt;5088 ulong cnt;
5067 bool error= FALSE;5089 bool error= FALSE;
5068 struct timespec curr_clock;5090 struct timespec curr_clock;
5091 bool binlog_prot_acquired= false;
50695092
5070 DBUG_ENTER("checkpoint_routine");5093 DBUG_ENTER("checkpoint_routine");
50715094
@@ -5137,9 +5160,32 @@
5137 sort_dynamic(&rli->least_occupied_workers, (qsort_cmp) ulong_cmp);5160 sort_dynamic(&rli->least_occupied_workers, (qsort_cmp) ulong_cmp);
51385161
5139 if (need_data_lock)5162 if (need_data_lock)
5163 {
5164 THD * const info_thd= rli->info_thd;
5165 const ulong timeout= info_thd->variables.lock_wait_timeout;
5166
5167 /*
5168 Acquire protection against global BINLOG lock before rli->data_lock is
5169 locked (otherwise we would also block SHOW SLAVE STATUS).
5170 */
5171 DBUG_ASSERT(!info_thd->backup_binlog_lock.is_acquired());
5172 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
5173 mysql_mutex_assert_not_owner(&rli->data_lock);
5174 error= info_thd->backup_binlog_lock.acquire_protection(info_thd,
5175 MDL_EXPLICIT,
5176 timeout);
5177 if (error)
5178 goto end;
5179
5180 binlog_prot_acquired= true;
5181
5140 mysql_mutex_lock(&rli->data_lock);5182 mysql_mutex_lock(&rli->data_lock);
5183 }
5141 else5184 else
5185 {
5142 mysql_mutex_assert_owner(&rli->data_lock);5186 mysql_mutex_assert_owner(&rli->data_lock);
5187 DBUG_ASSERT(rli->info_thd->backup_binlog_lock.is_protection_acquired());
5188 }
51435189
5144 /*5190 /*
5145 "Coordinator::commit_positions" {5191 "Coordinator::commit_positions" {
@@ -5184,6 +5230,13 @@
5184 /* end-of "Coordinator::"commit_positions" */5230 /* end-of "Coordinator::"commit_positions" */
51855231
5186end:5232end:
5233
5234 if (binlog_prot_acquired)
5235 {
5236 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
5237 rli->info_thd->backup_binlog_lock.release_protection(rli->info_thd);
5238 }
5239
5187#ifndef DBUG_OFF5240#ifndef DBUG_OFF
5188 if (DBUG_EVALUATE_IF("check_slave_debug_group", 1, 0))5241 if (DBUG_EVALUATE_IF("check_slave_debug_group", 1, 0))
5189 DBUG_SUICIDE();5242 DBUG_SUICIDE();
@@ -8134,6 +8187,7 @@
8134 my_off_t saved_log_pos= 0;8187 my_off_t saved_log_pos= 0;
8135 my_bool save_relay_log_purge= relay_log_purge;8188 my_bool save_relay_log_purge= relay_log_purge;
8136 bool mts_remove_workers= false;8189 bool mts_remove_workers= false;
8190 bool binlog_prot_acquired= false;
81378191
8138 DBUG_ENTER("change_master");8192 DBUG_ENTER("change_master");
81398193
@@ -8481,6 +8535,22 @@
8481 }8535 }
8482 relay_log_purge= save_relay_log_purge;8536 relay_log_purge= save_relay_log_purge;
84838537
8538 if (!thd->backup_binlog_lock.is_acquired())
8539 {
8540 const ulong timeout= thd->variables.lock_wait_timeout;
8541
8542 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
8543 mysql_mutex_assert_not_owner(&mi->rli->data_lock);
8544 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
8545 timeout))
8546 {
8547 ret= true;
8548 goto err;
8549 }
8550
8551 binlog_prot_acquired= true;
8552 }
8553
8484 /*8554 /*
8485 Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block,8555 Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block,
8486 so restore them to good values. If we left them to ''/0, that would work;8556 so restore them to good values. If we left them to ''/0, that would work;
@@ -8533,6 +8603,13 @@
8533 mysql_mutex_unlock(&mi->rli->data_lock);8603 mysql_mutex_unlock(&mi->rli->data_lock);
85348604
8535err:8605err:
8606
8607 if (binlog_prot_acquired)
8608 {
8609 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
8610 thd->backup_binlog_lock.release_protection(thd);
8611 }
8612
8536 unlock_slave_threads(mi);8613 unlock_slave_threads(mi);
8537 if (ret == FALSE)8614 if (ret == FALSE)
8538 {8615 {
85398616
=== modified file 'sql/sql_class.h'
--- sql/sql_class.h 2014-08-22 10:02:24 +0000
+++ sql/sql_class.h 2014-09-24 16:59:42 +0000
@@ -2170,6 +2170,8 @@
21702170
2171 bool is_acquired() const { return m_lock != NULL; }2171 bool is_acquired() const { return m_lock != NULL; }
21722172
2173 bool is_protection_acquired() const { return m_prot_lock != NULL; }
2174
2173private:2175private:
2174 MDL_key::enum_mdl_namespace m_namespace;2176 MDL_key::enum_mdl_namespace m_namespace;
2175 MDL_ticket *m_lock;2177 MDL_ticket *m_lock;

Subscribers

People subscribed via source and target branches