Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fabe3b6

Browse files
committed
Get rid of global_tx.c in_table implementation.
It was invented to deal with recovery-resolving deadlocks possible only on (at it seems) on 5+ nodes like - 1 prepares T1 on 1, 2, 3 - 4 prepares conflicting T2 on 4, 5 - Everyone fails, and only 2, 3, 5 go up. They can't recover without resolving at least one of xacts first because T1 and T2 conflict; and 'my orphaned xact which never got PRECOMMITted can be aborted directly' doesn't help here as no T1 neigher T2 authored by live nodes. To break out of this cycle, we could participate in voting normally, persisting xact as in_table before even getting PREPARE. However, it was very cumbersome and ugly; the process of in_table -> PREPARE state migration was especially baroque. Implementing accurately batch wal scan would also bring a lot of pain. There is a better idea: use generations to directly abort one of the xacts above. The connectivity clique forming majority will eventually elect its generation in which one of the nodes will be donor, i.e. will be immediately MTM_GEN_ONLINE. Any prepare which it doesn't have is subject to direct ABORT; it is the fundamental property of generations that node which is online in generation n has all committable PREPAREs of all <n gens.
1 parent 17b95e4 commit fabe3b6

10 files changed

+290
-784
lines changed

multimaster--1.0.sql

-11
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,6 @@ CREATE FUNCTION mtm.pg_lsn_to_bigint(lsn pg_lsn) RETURNS bigint AS $$
204204
$$
205205
LANGUAGE sql;
206206

207-
CREATE TABLE mtm.gtx_proposals(
208-
gid text primary key not null,
209-
-- defines the horizon after which record is not needed and can be deleted
210-
-- gtx_proposals contains only neighbours xacts, so this is truly origin_lsn
211-
-- origin node (coordinator) is encoded in gid
212-
prepare_origin_lsn pg_lsn,
213-
state text not null
214-
);
215-
/* proposals tables are private to nodes, don't stream them */
216-
INSERT INTO mtm.local_tables VALUES('mtm', 'gtx_proposals');
217-
218207
CREATE OR REPLACE FUNCTION mtm.alter_sequences() RETURNS boolean AS
219208
$$
220209
DECLARE

src/commit.c

+4-6
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,7 @@ mtm_commit_cleanup(int status, Datum arg)
143143
Assert(GetMyGlobalTx() != NULL || on_exit);
144144
if (GetMyGlobalTx() == NULL)
145145
mtm_commit_state.gtx = GlobalTxAcquire(mtm_commit_state.gid,
146-
false,
147-
NULL);
146+
false);
148147
/*
149148
* If we managed to prepare the xact, tell resolver to deal with it
150149
*/
@@ -445,7 +444,7 @@ MtmTwoPhaseCommit(void)
445444

446445
/* prepare transaction on our node */
447446

448-
mtm_commit_state.gtx = GlobalTxAcquire(mtm_commit_state.gid, true, NULL);
447+
mtm_commit_state.gtx = GlobalTxAcquire(mtm_commit_state.gid, true);
449448
Assert(mtm_commit_state.gtx->state.status == GTXInvalid);
450449
/*
451450
* PREPARE doesn't happen here; ret 0 just means we were already in
@@ -463,11 +462,10 @@ MtmTwoPhaseCommit(void)
463462
ReleasePB(); /* don't hold generation switch anymore */
464463
mtm_commit_state.gtx->prepared = true;
465464
/* end_lsn of PREPARE */
466-
mtm_commit_state.gtx->coordinator_end_lsn = XactLastCommitEnd;
467465
mtm_log(MtmTxFinish, "TXFINISH: %s prepared at %X/%X",
468466
mtm_commit_state.gid,
469-
(uint32) (mtm_commit_state.gtx->coordinator_end_lsn >> 32),
470-
(uint32) mtm_commit_state.gtx->coordinator_end_lsn);
467+
(uint32) (XactLastCommitEnd >> 32),
468+
(uint32) (XactLastCommitEnd));
471469

472470
/*
473471
* By definition of generations, we must collect PREPARE ack from

0 commit comments

Comments
 (0)