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

Commit bdc2e7a

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 60cc241 commit bdc2e7a

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
@@ -78,6 +78,8 @@ typedef struct FixedParallelState
7878
PGPROC *parallel_master_pgproc;
7979
pid_t parallel_master_pid;
8080
BackendId parallel_master_backend_id;
81+
TimestampTz xact_ts;
82+
TimestampTz stmt_ts;
8183

8284
/* Entrypoint for parallel workers (deprecated)! */
8385
parallel_worker_main_type entrypoint;
@@ -324,6 +326,8 @@ InitializeParallelDSM(ParallelContext *pcxt)
324326
fps->parallel_master_pgproc = MyProc;
325327
fps->parallel_master_pid = MyProcPid;
326328
fps->parallel_master_backend_id = MyBackendId;
329+
fps->xact_ts = GetCurrentTransactionStartTimestamp();
330+
fps->stmt_ts = GetCurrentStatementStartTimestamp();
327331
fps->entrypoint = pcxt->entrypoint;
328332
SpinLockInit(&fps->mutex);
329333
fps->last_xlog_end = 0;
@@ -1148,6 +1152,13 @@ ParallelWorkerMain(Datum main_arg)
11481152
fps->parallel_master_pid))
11491153
return;
11501154

1155+
/*
1156+
* Restore transaction and statement start-time timestamps. This must
1157+
* happen before anything that would start a transaction, else asserts in
1158+
* xact.c will fire.
1159+
*/
1160+
SetParallelStartTimestamps(fps->xact_ts, fps->stmt_ts);
1161+
11511162
/*
11521163
* Identify the entry point to be called. In theory this could result in
11531164
* 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
@@ -698,6 +698,22 @@ GetCurrentCommandId(bool used)
698698
return currentCommandId;
699699
}
700700

701+
/*
702+
* SetParallelStartTimestamps
703+
*
704+
* In a parallel worker, we should inherit the parent transaction's
705+
* timestamps rather than setting our own. The parallel worker
706+
* infrastructure must call this to provide those values before
707+
* calling StartTransaction() or SetCurrentStatementStartTimestamp().
708+
*/
709+
void
710+
SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
711+
{
712+
Assert(IsParallelWorker());
713+
xactStartTimestamp = xact_ts;
714+
stmtStartTimestamp = stmt_ts;
715+
}
716+
701717
/*
702718
* GetCurrentTransactionStartTimestamp
703719
*/
@@ -732,11 +748,17 @@ GetCurrentTransactionStopTimestamp(void)
732748

733749
/*
734750
* SetCurrentStatementStartTimestamp
751+
*
752+
* In a parallel worker, this should already have been provided by a call
753+
* to SetParallelStartTimestamps().
735754
*/
736755
void
737756
SetCurrentStatementStartTimestamp(void)
738757
{
739-
stmtStartTimestamp = GetCurrentTimestamp();
758+
if (!IsParallelWorker())
759+
stmtStartTimestamp = GetCurrentTimestamp();
760+
else
761+
Assert(stmtStartTimestamp != 0);
740762
}
741763

742764
/*
@@ -1889,10 +1911,16 @@ StartTransaction(void)
18891911
/*
18901912
* set transaction_timestamp() (a/k/a now()). We want this to be the same
18911913
* as the first command's statement_timestamp(), so don't do a fresh
1892-
* GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1893-
* xactStopTimestamp as unset.
1914+
* GetCurrentTimestamp() call (which'd be expensive anyway). In a
1915+
* parallel worker, this should already have been provided by a call to
1916+
* SetParallelStartTimestamps().
1917+
*
1918+
* Also, mark xactStopTimestamp as unset.
18941919
*/
1895-
xactStartTimestamp = stmtStartTimestamp;
1920+
if (!IsParallelWorker())
1921+
xactStartTimestamp = stmtStartTimestamp;
1922+
else
1923+
Assert(xactStartTimestamp != 0);
18961924
xactStopTimestamp = 0;
18971925
pgstat_report_xact_timestamp(xactStartTimestamp);
18981926

src/include/access/xact.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ extern SubTransactionId GetCurrentSubTransactionId(void);
318318
extern void MarkCurrentTransactionIdLoggedIfAny(void);
319319
extern bool SubTransactionIsActive(SubTransactionId subxid);
320320
extern CommandId GetCurrentCommandId(bool used);
321+
extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
321322
extern TimestampTz GetCurrentTransactionStartTimestamp(void);
322323
extern TimestampTz GetCurrentStatementStartTimestamp(void);
323324
extern TimestampTz GetCurrentTransactionStopTimestamp(void);

0 commit comments

Comments
 (0)