Skip to content

Commit 040b840

Browse files
committed
MDEV-15740 Backport wsrep recovery fixes from 10.4.
Clear wsrep XID in innobase_rollback_by_xid() for recovered wsrep transaction in order to avoid resetting XID storage when rolling back wsrep transaction during recovery. Sort wsrep XIDs read from storage engine in ascending order and erify that the range is continuous during crash recovery. If binlog is off, commit all recovered transactions for continuous seqno range. This is safe because all transactions with wsrep XID have been certified and must be committed in the cluster. On the other hand if binlog is on, respect binlog as a transaction coordinator in order to avoid missing transactions in binlog that have been committed into storage engine .
1 parent ce28fa5 commit 040b840

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

sql/handler.cc

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,35 @@ static char* xid_to_str(char *buf, XID *xid)
18271827
}
18281828
#endif
18291829

1830+
#ifdef WITH_WSREP
1831+
static my_xid wsrep_order_and_check_continuity(XID *list, int len)
1832+
{
1833+
wsrep_sort_xid_array(list, len);
1834+
wsrep_uuid_t uuid;
1835+
wsrep_seqno_t seqno;
1836+
if (wsrep_get_SE_checkpoint(uuid, seqno))
1837+
{
1838+
WSREP_ERROR("Could not read wsrep SE checkpoint for recovery");
1839+
return 0;
1840+
}
1841+
long long cur_seqno= seqno;
1842+
for (int i= 0; i < len; ++i)
1843+
{
1844+
if (!wsrep_is_wsrep_xid(list + i) ||
1845+
wsrep_xid_seqno(*(list + i)) != cur_seqno + 1)
1846+
{
1847+
WSREP_WARN("Discovered discontinuity in recovered wsrep "
1848+
"transaction XIDs. Truncating the recovery list to "
1849+
"%d entries", i);
1850+
break;
1851+
}
1852+
++cur_seqno;
1853+
}
1854+
WSREP_INFO("Last wsrep seqno to be recovered %lld", cur_seqno);
1855+
return (cur_seqno < 0 ? 0 : cur_seqno);
1856+
}
1857+
#endif /* WITH_WSREP */
1858+
18301859
/**
18311860
recover() step of xa.
18321861
@@ -1864,6 +1893,19 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
18641893
{
18651894
sql_print_information("Found %d prepared transaction(s) in %s",
18661895
got, hton_name(hton)->str);
1896+
#ifdef WITH_WSREP
1897+
/* If wsrep_on=ON, XIDs are first ordered and then the range of
1898+
recovered XIDs is checked for continuity. All the XIDs which
1899+
are in continuous range can be safely committed if binlog
1900+
is off since they have already ordered and certified in the
1901+
cluster. */
1902+
my_xid wsrep_limit= 0;
1903+
if (WSREP_ON)
1904+
{
1905+
wsrep_limit= wsrep_order_and_check_continuity(info->list, got);
1906+
}
1907+
#endif /* WITH_WSREP */
1908+
18671909
for (int i=0; i < got; i ++)
18681910
{
18691911
my_xid x= WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ?
@@ -1885,9 +1927,12 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
18851927
continue;
18861928
}
18871929
// recovery mode
1888-
if (info->commit_list ?
1889-
my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
1890-
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1930+
if (IF_WSREP((wsrep_emulate_bin_log &&
1931+
wsrep_is_wsrep_xid(info->list + i) &&
1932+
x <= wsrep_limit), false) ||
1933+
(info->commit_list ?
1934+
my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
1935+
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT))
18911936
{
18921937
#ifndef DBUG_OFF
18931938
int rc=

sql/wsrep_xid.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "sql_class.h"
2121
#include "wsrep_mysqld.h" // for logging macros
2222

23+
#include <algorithm> /* std::sort() */
24+
2325
/*
2426
* WSREPXid
2527
*/
@@ -154,3 +156,35 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
154156

155157
return false;
156158
}
159+
160+
/*
161+
Sort order for XIDs. Wsrep XIDs are sorted according to
162+
seqno in ascending order. Non-wsrep XIDs are considered
163+
equal among themselves and greater than with respect
164+
to wsrep XIDs.
165+
*/
166+
struct Wsrep_xid_cmp
167+
{
168+
bool operator()(const XID& left, const XID& right) const
169+
{
170+
const bool left_is_wsrep= wsrep_is_wsrep_xid(&left);
171+
const bool right_is_wsrep= wsrep_is_wsrep_xid(&right);
172+
if (left_is_wsrep && right_is_wsrep)
173+
{
174+
return (wsrep_xid_seqno(left) < wsrep_xid_seqno(right));
175+
}
176+
else if (left_is_wsrep)
177+
{
178+
return true;
179+
}
180+
else
181+
{
182+
return false;
183+
}
184+
}
185+
};
186+
187+
void wsrep_sort_xid_array(XID *array, int len)
188+
{
189+
std::sort(array, array + len, Wsrep_xid_cmp());
190+
}

sql/wsrep_xid.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,7 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&);
3232
//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */
3333
bool wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t);
3434

35+
void wsrep_sort_xid_array(XID *array, int len);
36+
3537
#endif /* WITH_WSREP */
3638
#endif /* WSREP_UTILS_H */

storage/innobase/handler/ha_innodb.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17260,6 +17260,14 @@ innobase_rollback_by_xid(
1726017260
}
1726117261

1726217262
if (trx_t* trx = trx_get_trx_by_xid(xid)) {
17263+
#ifdef WITH_WSREP
17264+
/* If a wsrep transaction is being rolled back during
17265+
the recovery, we must clear the xid in order to avoid
17266+
writing serialisation history for rolled back transaction. */
17267+
if (wsrep_is_wsrep_xid(trx->xid)) {
17268+
trx->xid->null();
17269+
}
17270+
#endif /* WITH_WSREP */
1726317271
int ret = innobase_rollback_trx(trx);
1726417272
trx_deregister_from_2pc(trx);
1726517273
ut_ad(!trx->will_lock);

0 commit comments

Comments
 (0)