Skip to content

Commit d0c8316

Browse files
authored
Incorrect behaviour of WSREP_SYNC_WAIT_UPTO_GTID (#1442)
Function `signal_waiters` assigned `m_committed_seqno` variable outside of mutex lock which caused incorrect behavior of WSREP_SYNC_WAIT_UPTO_GTID. Fixed by moving assignment inside lock. Added handling of OOM and now error is reported. Remove hard-coded seqno value and read seqno directly from current node state.
1 parent daaa881 commit d0c8316

File tree

4 files changed

+42
-28
lines changed

4 files changed

+42
-28
lines changed

mysql-test/suite/galera/r/galera_sync_wait_upto.result

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ WSREP_SYNC_WAIT_UPTO
1616
1
1717
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
1818
connection node_2;
19-
SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-3');
2019
connection node_1;
2120
INSERT INTO t1 VALUES (2);
2221
connection node_2;
23-
WSREP_SYNC_WAIT_UPTO_GTID('100-1-3')
22+
WSREP_SYNC_WAIT_UPTO
2423
1
2524
connection node_1;
2625
DROP TABLE t1;

mysql-test/suite/galera/t/galera_sync_wait_upto.test

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ SELECT WSREP_SYNC_WAIT_UPTO_GTID('1-1-1,1-1-2');
2424

2525
# Expected starting seqno
2626

27-
--let $start_seqno = 2
27+
--let $last_seen_gtid = `SELECT WSREP_LAST_SEEN_GTID()`
28+
--let $s1 = `SELECT SUBSTR('$last_seen_gtid', LOCATE('-', '$last_seen_gtid') + LENGTH('-'))`
29+
--let $start_seqno = `SELECT SUBSTR('$s1', LOCATE('-', '$s1') + LENGTH('-'))`
2830

2931
# If set to low value, expect no waiting
3032

@@ -57,10 +59,9 @@ SELECT WSREP_SYNC_WAIT_UPTO_GTID('1-1-1,1-1-2');
5759
--disable_query_log
5860
--let $wait_seqno = $start_seqno
5961
--inc $wait_seqno
62+
--send_eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-$wait_seqno') AS WSREP_SYNC_WAIT_UPTO
6063
--enable_query_log
6164

62-
--send_eval SELECT WSREP_SYNC_WAIT_UPTO_GTID('100-1-$wait_seqno')
63-
6465
--connection node_1
6566
INSERT INTO t1 VALUES (2);
6667

sql/item_strfunc.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5297,6 +5297,7 @@ longlong Item_func_wsrep_sync_wait_upto::val_int()
52975297
uint timeout;
52985298
rpl_gtid *gtid_list;
52995299
uint32 count;
5300+
int wait_gtid_ret= 0;
53005301
int ret= 1;
53015302

53025303
if (args[0]->null_value)
@@ -5323,11 +5324,17 @@ longlong Item_func_wsrep_sync_wait_upto::val_int()
53235324
if (wsrep_check_gtid_seqno(gtid_list[0].domain_id, gtid_list[0].server_id,
53245325
gtid_list[0].seq_no))
53255326
{
5326-
if (wsrep_gtid_server.wait_gtid_upto(gtid_list[0].seq_no, timeout))
5327+
wait_gtid_ret= wsrep_gtid_server.wait_gtid_upto(gtid_list[0].seq_no, timeout);
5328+
if ((wait_gtid_ret == ETIMEDOUT) || (wait_gtid_ret == ETIME))
53275329
{
53285330
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), func_name());
53295331
ret= 0;
53305332
}
5333+
else if (wait_gtid_ret == ENOMEM)
5334+
{
5335+
my_error(ER_OUTOFMEMORY, MYF(0), func_name());
5336+
ret= 0;
5337+
}
53315338
}
53325339
}
53335340
else

sql/wsrep_mysqld.h

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -431,45 +431,52 @@ class Wsrep_gtid_server
431431
}
432432
int wait_gtid_upto(const uint64_t seqno, uint timeout)
433433
{
434-
int wait_result;
434+
int wait_result= 0;
435435
struct timespec wait_time;
436436
int ret= 0;
437437
mysql_cond_t wait_cond;
438438
mysql_cond_init(key_COND_wsrep_gtid_wait_upto, &wait_cond, NULL);
439439
set_timespec(wait_time, timeout);
440440
mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto);
441441
std::multimap<uint64, mysql_cond_t*>::iterator it;
442-
try
442+
if (seqno > m_seqno)
443443
{
444-
it= m_wait_map.insert(std::make_pair(seqno, &wait_cond));
445-
}
446-
catch (std::bad_alloc& e)
447-
{
448-
return 0;
449-
}
450-
while ((m_committed_seqno < seqno) && !m_force_signal)
451-
{
452-
wait_result= mysql_cond_timedwait(&wait_cond,
453-
&LOCK_wsrep_gtid_wait_upto,
454-
&wait_time);
455-
if (wait_result == ETIMEDOUT || wait_result == ETIME)
444+
try
456445
{
457-
ret= 1;
458-
break;
446+
it= m_wait_map.insert(std::make_pair(seqno, &wait_cond));
447+
}
448+
catch (std::bad_alloc& e)
449+
{
450+
ret= ENOMEM;
451+
}
452+
while (!ret && (m_committed_seqno < seqno) && !m_force_signal)
453+
{
454+
wait_result= mysql_cond_timedwait(&wait_cond,
455+
&LOCK_wsrep_gtid_wait_upto,
456+
&wait_time);
457+
if (wait_result == ETIMEDOUT || wait_result == ETIME)
458+
{
459+
ret= wait_result;
460+
break;
461+
}
462+
}
463+
if (ret != ENOMEM)
464+
{
465+
m_wait_map.erase(it);
459466
}
460467
}
461-
m_wait_map.erase(it);
462468
mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto);
463469
mysql_cond_destroy(&wait_cond);
464470
return ret;
465471
}
466472
void signal_waiters(uint64 seqno, bool signal_all)
467473
{
474+
mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto);
468475
if (!signal_all && (m_committed_seqno >= seqno))
469476
{
477+
mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto);
470478
return;
471479
}
472-
mysql_mutex_lock(&LOCK_wsrep_gtid_wait_upto);
473480
m_force_signal= true;
474481
std::multimap<uint64, mysql_cond_t*>::iterator it_end;
475482
std::multimap<uint64, mysql_cond_t*>::iterator it_begin;
@@ -481,16 +488,16 @@ class Wsrep_gtid_server
481488
{
482489
it_end= m_wait_map.upper_bound(seqno);
483490
}
491+
if (m_committed_seqno < seqno)
492+
{
493+
m_committed_seqno= seqno;
494+
}
484495
for (it_begin = m_wait_map.begin(); it_begin != it_end; ++it_begin)
485496
{
486497
mysql_cond_signal(it_begin->second);
487498
}
488499
m_force_signal= false;
489500
mysql_mutex_unlock(&LOCK_wsrep_gtid_wait_upto);
490-
if (m_committed_seqno < seqno)
491-
{
492-
m_committed_seqno= seqno;
493-
}
494501
}
495502
private:
496503
const wsrep_server_gtid_t m_undefined= {0,0,0};

0 commit comments

Comments
 (0)