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

Commit 6bf278d

Browse files
committed
Propagate xactStartTimestamp and stmtStartTimestamp to parallel workers.
Previously, a worker process would establish values for these based on its own start time. In v10 and up, this can trivially be shown to cause misbehavior of transaction_timestamp(), timestamp_in(), and related functions which are (perhaps unwisely?) marked parallel-safe. It seems likely that other behaviors might diverge from what happens in the parent as well. It's not as trivial to demonstrate problems in 9.6 or 9.5, but I'm sure it's still possible, so back-patch to all branches containing parallel worker infrastructure. In HEAD only, mark now() and statement_timestamp() as parallel-safe (other affected functions already were). While in theory we could still squeeze that change into v11, it doesn't seem important enough to force a last-minute catversion bump. Konstantin Knizhnik, whacked around a bit by me Discussion: https://postgr.es/m/6406dbd2-5d37-4cb6-6eb2-9c44172c7e7c@postgrespro.ru
1 parent c905b67 commit 6bf278d

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

src/backend/access/transam/parallel.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ typedef struct FixedParallelState
8686
PGPROC *parallel_master_pgproc;
8787
pid_t parallel_master_pid;
8888
BackendId parallel_master_backend_id;
89+
TimestampTz xact_ts;
90+
TimestampTz stmt_ts;
8991

9092
/* Mutex protects remaining fields. */
9193
slock_t mutex;
@@ -321,6 +323,8 @@ InitializeParallelDSM(ParallelContext *pcxt)
321323
fps->parallel_master_pgproc = MyProc;
322324
fps->parallel_master_pid = MyProcPid;
323325
fps->parallel_master_backend_id = MyBackendId;
326+
fps->xact_ts = GetCurrentTransactionStartTimestamp();
327+
fps->stmt_ts = GetCurrentStatementStartTimestamp();
324328
SpinLockInit(&fps->mutex);
325329
fps->last_xlog_end = 0;
326330
shm_toc_insert(pcxt->toc, PARALLEL_KEY_FIXED, fps);
@@ -1303,6 +1307,13 @@ ParallelWorkerMain(Datum main_arg)
13031307
fps->parallel_master_pid))
13041308
return;
13051309

1310+
/*
1311+
* Restore transaction and statement start-time timestamps. This must
1312+
* happen before anything that would start a transaction, else asserts in
1313+
* xact.c will fire.
1314+
*/
1315+
SetParallelStartTimestamps(fps->xact_ts, fps->stmt_ts);
1316+
13061317
/*
13071318
* Identify the entry point to be called. In theory this could result in
13081319
* loading an additional library, though most likely the entry point is in

src/backend/access/transam/xact.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,22 @@ GetCurrentCommandId(bool used)
693693
return currentCommandId;
694694
}
695695

696+
/*
697+
* SetParallelStartTimestamps
698+
*
699+
* In a parallel worker, we should inherit the parent transaction's
700+
* timestamps rather than setting our own. The parallel worker
701+
* infrastructure must call this to provide those values before
702+
* calling StartTransaction() or SetCurrentStatementStartTimestamp().
703+
*/
704+
void
705+
SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
706+
{
707+
Assert(IsParallelWorker());
708+
xactStartTimestamp = xact_ts;
709+
stmtStartTimestamp = stmt_ts;
710+
}
711+
696712
/*
697713
* GetCurrentTransactionStartTimestamp
698714
*/
@@ -727,11 +743,17 @@ GetCurrentTransactionStopTimestamp(void)
727743

728744
/*
729745
* SetCurrentStatementStartTimestamp
746+
*
747+
* In a parallel worker, this should already have been provided by a call
748+
* to SetParallelStartTimestamps().
730749
*/
731750
void
732751
SetCurrentStatementStartTimestamp(void)
733752
{
734-
stmtStartTimestamp = GetCurrentTimestamp();
753+
if (!IsParallelWorker())
754+
stmtStartTimestamp = GetCurrentTimestamp();
755+
else
756+
Assert(stmtStartTimestamp != 0);
735757
}
736758

737759
/*
@@ -1886,10 +1908,16 @@ StartTransaction(void)
18861908
/*
18871909
* set transaction_timestamp() (a/k/a now()). We want this to be the same
18881910
* as the first command's statement_timestamp(), so don't do a fresh
1889-
* GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1890-
* xactStopTimestamp as unset.
1911+
* GetCurrentTimestamp() call (which'd be expensive anyway). In a
1912+
* parallel worker, this should already have been provided by a call to
1913+
* SetParallelStartTimestamps().
1914+
*
1915+
* Also, mark xactStopTimestamp as unset.
18911916
*/
1892-
xactStartTimestamp = stmtStartTimestamp;
1917+
if (!IsParallelWorker())
1918+
xactStartTimestamp = stmtStartTimestamp;
1919+
else
1920+
Assert(xactStartTimestamp != 0);
18931921
xactStopTimestamp = 0;
18941922
pgstat_report_xact_timestamp(xactStartTimestamp);
18951923

src/include/access/xact.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ extern SubTransactionId GetCurrentSubTransactionId(void);
359359
extern void MarkCurrentTransactionIdLoggedIfAny(void);
360360
extern bool SubTransactionIsActive(SubTransactionId subxid);
361361
extern CommandId GetCurrentCommandId(bool used);
362+
extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
362363
extern TimestampTz GetCurrentTransactionStartTimestamp(void);
363364
extern TimestampTz GetCurrentStatementStartTimestamp(void);
364365
extern TimestampTz GetCurrentTransactionStopTimestamp(void);

0 commit comments

Comments
 (0)