Skip to content

Commit 756c6e9

Browse files
committed
Commit stalled precommited transactions in case of single node alive
1 parent 9e8de2e commit 756c6e9

File tree

4 files changed

+24
-9
lines changed

4 files changed

+24
-9
lines changed

multimaster.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,9 +1958,11 @@ void MtmHandleApplyError(void)
19581958
* Actually, if node is precommitted (state == UNKNOWN) at any of nodes, then is is prepared at all nodes and so can be committed.
19591959
* But if coordinator of transaction is crashed, we made a decision about transaction commit only if transaction is precommitted at ALL live nodes.
19601960
* The reason is that we want to avoid extra polling to obtain maximum CSN from all nodes to assign it to committed transaction.
1961-
* Called only from MtmDisableNode in critical section.
1961+
* Called only from MtmDisableNode and in major mode.
1962+
*
1963+
* commitPrecommited is used when nnodes=2 and we are switching to major/referee mode.
19621964
*/
1963-
void MtmPollStatusOfPreparedTransactionsForDisabledNode(int disabledNodeId)
1965+
void MtmPollStatusOfPreparedTransactionsForDisabledNode(int disabledNodeId, bool commitPrecommited)
19641966
{
19651967
MtmTransState *ts;
19661968
for (ts = Mtm->transListHead; ts != NULL; ts = ts->next) {
@@ -1974,8 +1976,15 @@ void MtmPollStatusOfPreparedTransactionsForDisabledNode(int disabledNodeId)
19741976
MTM_ELOG(LOG, "Abort transaction %s because its coordinator is disabled and it is not prepared at node %d", ts->gid, MtmNodeId);
19751977
MtmFinishPreparedTransaction(ts, false);
19761978
} else {
1977-
MTM_LOG1("Poll state of transaction %s (%llu)", ts->gid, (long64)ts->xid);
1978-
MtmBroadcastPollMessage(ts);
1979+
if (commitPrecommited)
1980+
{
1981+
MtmFinishPreparedTransaction(ts, true);
1982+
}
1983+
else
1984+
{
1985+
MTM_LOG1("Poll state of transaction %s (%llu)", ts->gid, (long64)ts->xid);
1986+
MtmBroadcastPollMessage(ts);
1987+
}
19791988
}
19801989
} else {
19811990
MTM_LOG2("Skip transaction %s (%llu) with status %s gtid.node=%d gtid.xid=%llu votedMask=%llx",

multimaster.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ extern void MtmReleaseLocks(void);
445445
extern void MtmInitMessage(MtmArbiterMessage* msg, MtmMessageCode code);
446446
extern void MtmSetSnapshot(csn_t snapshot);
447447
extern void MtmRefereeInitialize(void);
448-
extern void MtmPollStatusOfPreparedTransactionsForDisabledNode(int disabledNodeId);
448+
extern void MtmPollStatusOfPreparedTransactionsForDisabledNode(int disabledNodeId, bool commitPrecommited);
449449
extern int MtmGetNumberOfVotingNodes(void);
450450

451451
#endif

state.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ MtmSetClusterStatus(MtmNodeStatus status)
7171
Mtm->recoverySlot = 0;
7272
Mtm->pglogicalReceiverMask = 0;
7373
Mtm->pglogicalSenderMask = 0;
74-
// XXXX: better to enable, but not now. It requires better testing
75-
// Mtm->recoveryCount++; /* this will restart replication connection */
74+
Mtm->recoveryCount++; /* this will restart replication connection */
7675
}
7776

7877
Mtm->status = status;
@@ -270,7 +269,7 @@ void MtmDisableNode(int nodeId)
270269
if (Mtm->status == MTM_ONLINE) {
271270
/* Make decision about prepared transaction status only in quorum */
272271
MtmLock(LW_EXCLUSIVE);
273-
MtmPollStatusOfPreparedTransactionsForDisabledNode(nodeId);
272+
MtmPollStatusOfPreparedTransactionsForDisabledNode(nodeId, false);
274273
MtmUnlock();
275274
}
276275
}
@@ -411,6 +410,13 @@ MtmRefreshClusterStatus()
411410
winner_node_id);
412411
Mtm->refereeGrant = true;
413412
MtmLock(LW_EXCLUSIVE);
413+
if (countZeroBits(SELF_CONNECTIVITY_MASK, Mtm->nAllNodes) == 1)
414+
{
415+
// XXXX: that is valid for two nodes. Better idea is to parametrize MtmPollStatus*
416+
// functions.
417+
int neighbor_node_id = MtmNodeId == 1 ? 2 : 1;
418+
MtmPollStatusOfPreparedTransactionsForDisabledNode(neighbor_node_id, true);
419+
}
414420
MtmEnableNode(MtmNodeId);
415421
MtmCheckState();
416422
MtmUnlock();

tests2/lib/bank_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,9 @@ def total_tx(self, conn, cur, agg, conn_i):
255255
total = yield from cur.fetchone()
256256
if total[0] != self.total:
257257
agg.isolation += 1
258+
print(datetime.datetime.utcnow(), 'Isolation error, total ', self.total, ' -> ', total[0], ', node ', conn_i+1)
258259
self.total = total[0]
259260
print(self.oops)
260-
print(datetime.datetime.utcnow(), 'Isolation error, total = ', total, ', node ', conn_i+1)
261261
# yield from cur.execute('select * from mtm.get_nodes_state()')
262262
# nodes_state = yield from cur.fetchall()
263263
# for i, col in enumerate(self.nodes_state_fields):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy