Commit c4320619 authored by Tom Lane's avatar Tom Lane

Change the timestamps recorded in transaction commit/abort xlog records

from time_t to TimestampTz representation.  This provides full gettimeofday()
resolution of the timestamps, which might be useful when attempting to
do point-in-time recovery --- previously it was not possible to specify
the stop point with sub-second resolution.  But mostly this is to get
rid of TimestampTz-to-time_t conversion overhead during commit.  Per my
proposal of a day or two back.
parent 641912b4
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.29 2007/04/03 16:34:35 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.30 2007/04/30 21:01:52 tgl Exp $
* *
* NOTES * NOTES
* Each global transaction is associated with a global transaction * Each global transaction is associated with a global transaction
...@@ -1675,7 +1675,7 @@ RecordTransactionCommitPrepared(TransactionId xid, ...@@ -1675,7 +1675,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
/* Emit the XLOG commit record */ /* Emit the XLOG commit record */
xlrec.xid = xid; xlrec.xid = xid;
xlrec.crec.xtime = time(NULL); xlrec.crec.xact_time = GetCurrentTimestamp();
xlrec.crec.nrels = nrels; xlrec.crec.nrels = nrels;
xlrec.crec.nsubxacts = nchildren; xlrec.crec.nsubxacts = nchildren;
rdata[0].data = (char *) (&xlrec); rdata[0].data = (char *) (&xlrec);
...@@ -1753,7 +1753,7 @@ RecordTransactionAbortPrepared(TransactionId xid, ...@@ -1753,7 +1753,7 @@ RecordTransactionAbortPrepared(TransactionId xid,
/* Emit the XLOG abort record */ /* Emit the XLOG abort record */
xlrec.xid = xid; xlrec.xid = xid;
xlrec.arec.xtime = time(NULL); xlrec.arec.xact_time = GetCurrentTimestamp();
xlrec.arec.nrels = nrels; xlrec.arec.nrels = nrels;
xlrec.arec.nsubxacts = nchildren; xlrec.arec.nsubxacts = nchildren;
rdata[0].data = (char *) (&xlrec); rdata[0].data = (char *) (&xlrec);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.241 2007/04/30 03:23:48 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.242 2007/04/30 21:01:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -773,7 +773,7 @@ RecordTransactionCommit(void) ...@@ -773,7 +773,7 @@ RecordTransactionCommit(void)
MyProc->inCommit = true; MyProc->inCommit = true;
SetCurrentTransactionStopTimestamp(); SetCurrentTransactionStopTimestamp();
xlrec.xtime = timestamptz_to_time_t(xactStopTimestamp); xlrec.xact_time = xactStopTimestamp;
xlrec.nrels = nrels; xlrec.nrels = nrels;
xlrec.nsubxacts = nchildren; xlrec.nsubxacts = nchildren;
rdata[0].data = (char *) (&xlrec); rdata[0].data = (char *) (&xlrec);
...@@ -1069,7 +1069,7 @@ RecordTransactionAbort(void) ...@@ -1069,7 +1069,7 @@ RecordTransactionAbort(void)
XLogRecPtr recptr; XLogRecPtr recptr;
SetCurrentTransactionStopTimestamp(); SetCurrentTransactionStopTimestamp();
xlrec.xtime = timestamptz_to_time_t(xactStopTimestamp); xlrec.xact_time = xactStopTimestamp;
xlrec.nrels = nrels; xlrec.nrels = nrels;
xlrec.nsubxacts = nchildren; xlrec.nsubxacts = nchildren;
rdata[0].data = (char *) (&xlrec); rdata[0].data = (char *) (&xlrec);
...@@ -1247,7 +1247,7 @@ RecordSubTransactionAbort(void) ...@@ -1247,7 +1247,7 @@ RecordSubTransactionAbort(void)
xl_xact_abort xlrec; xl_xact_abort xlrec;
XLogRecPtr recptr; XLogRecPtr recptr;
xlrec.xtime = time(NULL); xlrec.xact_time = GetCurrentTimestamp();
xlrec.nrels = nrels; xlrec.nrels = nrels;
xlrec.nsubxacts = nchildren; xlrec.nsubxacts = nchildren;
rdata[0].data = (char *) (&xlrec); rdata[0].data = (char *) (&xlrec);
...@@ -4282,12 +4282,9 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -4282,12 +4282,9 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
static void static void
xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec) xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
{ {
struct tm *tm = localtime(&xlrec->xtime);
int i; int i;
appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u", appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
if (xlrec->nrels > 0) if (xlrec->nrels > 0)
{ {
appendStringInfo(buf, "; rels:"); appendStringInfo(buf, "; rels:");
...@@ -4313,12 +4310,9 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec) ...@@ -4313,12 +4310,9 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
static void static void
xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec) xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
{ {
struct tm *tm = localtime(&xlrec->xtime);
int i; int i;
appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u", appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
if (xlrec->nrels > 0) if (xlrec->nrels > 0)
{ {
appendStringInfo(buf, "; rels:"); appendStringInfo(buf, "; rels:");
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.267 2007/04/03 16:34:35 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.268 2007/04/30 21:01:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include "storage/procarray.h" #include "storage/procarray.h"
#include "storage/spin.h" #include "storage/spin.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/nabstime.h"
#include "utils/pg_locale.h" #include "utils/pg_locale.h"
...@@ -114,11 +113,11 @@ static bool recoveryTarget = false; ...@@ -114,11 +113,11 @@ static bool recoveryTarget = false;
static bool recoveryTargetExact = false; static bool recoveryTargetExact = false;
static bool recoveryTargetInclusive = true; static bool recoveryTargetInclusive = true;
static TransactionId recoveryTargetXid; static TransactionId recoveryTargetXid;
static time_t recoveryTargetTime; static TimestampTz recoveryTargetTime;
/* if recoveryStopsHere returns true, it saves actual stop xid/time here */ /* if recoveryStopsHere returns true, it saves actual stop xid/time here */
static TransactionId recoveryStopXid; static TransactionId recoveryStopXid;
static time_t recoveryStopTime; static TimestampTz recoveryStopTime;
static bool recoveryStopAfter; static bool recoveryStopAfter;
/* /*
...@@ -3536,7 +3535,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, ...@@ -3536,7 +3535,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
xlogfname, xlogfname,
recoveryStopAfter ? "after" : "before", recoveryStopAfter ? "after" : "before",
recoveryStopXid, recoveryStopXid,
str_time(recoveryStopTime)); timestamptz_to_str(recoveryStopTime));
nbytes = strlen(buffer); nbytes = strlen(buffer);
errno = 0; errno = 0;
...@@ -4276,17 +4275,16 @@ readRecoveryCommandFile(void) ...@@ -4276,17 +4275,16 @@ readRecoveryCommandFile(void)
recoveryTargetExact = false; recoveryTargetExact = false;
/* /*
* Convert the time string given by the user to the time_t format. * Convert the time string given by the user to TimestampTz form.
* We use type abstime's input converter because we know abstime
* has the same representation as time_t.
*/ */
recoveryTargetTime = (time_t) recoveryTargetTime =
DatumGetAbsoluteTime(DirectFunctionCall1(abstimein, DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
CStringGetDatum(tok2))); CStringGetDatum(tok2),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1)));
ereport(LOG, ereport(LOG,
(errmsg("recovery_target_time = %s", (errmsg("recovery_target_time = %s",
DatumGetCString(DirectFunctionCall1(abstimeout, timestamptz_to_str(recoveryTargetTime))));
AbsoluteTimeGetDatum((AbsoluteTime) recoveryTargetTime))))));
} }
else if (strcmp(tok1, "recovery_target_inclusive") == 0) else if (strcmp(tok1, "recovery_target_inclusive") == 0)
{ {
...@@ -4464,7 +4462,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -4464,7 +4462,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
{ {
bool stopsHere; bool stopsHere;
uint8 record_info; uint8 record_info;
time_t recordXtime; TimestampTz recordXtime;
/* Do we have a PITR target at all? */ /* Do we have a PITR target at all? */
if (!recoveryTarget) if (!recoveryTarget)
...@@ -4479,14 +4477,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -4479,14 +4477,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
xl_xact_commit *recordXactCommitData; xl_xact_commit *recordXactCommitData;
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record); recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
recordXtime = recordXactCommitData->xtime; recordXtime = recordXactCommitData->xact_time;
} }
else if (record_info == XLOG_XACT_ABORT) else if (record_info == XLOG_XACT_ABORT)
{ {
xl_xact_abort *recordXactAbortData; xl_xact_abort *recordXactAbortData;
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record); recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
recordXtime = recordXactAbortData->xtime; recordXtime = recordXactAbortData->xact_time;
} }
else else
return false; return false;
...@@ -4532,22 +4530,26 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -4532,22 +4530,26 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
if (recoveryStopAfter) if (recoveryStopAfter)
ereport(LOG, ereport(LOG,
(errmsg("recovery stopping after commit of transaction %u, time %s", (errmsg("recovery stopping after commit of transaction %u, time %s",
recoveryStopXid, str_time(recoveryStopTime)))); recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
else else
ereport(LOG, ereport(LOG,
(errmsg("recovery stopping before commit of transaction %u, time %s", (errmsg("recovery stopping before commit of transaction %u, time %s",
recoveryStopXid, str_time(recoveryStopTime)))); recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
} }
else else
{ {
if (recoveryStopAfter) if (recoveryStopAfter)
ereport(LOG, ereport(LOG,
(errmsg("recovery stopping after abort of transaction %u, time %s", (errmsg("recovery stopping after abort of transaction %u, time %s",
recoveryStopXid, str_time(recoveryStopTime)))); recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
else else
ereport(LOG, ereport(LOG,
(errmsg("recovery stopping before abort of transaction %u, time %s", (errmsg("recovery stopping before abort of transaction %u, time %s",
recoveryStopXid, str_time(recoveryStopTime)))); recoveryStopXid,
timestamptz_to_str(recoveryStopTime))));
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.175 2007/04/30 03:23:49 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.176 2007/04/30 21:01:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1301,6 +1301,33 @@ timestamptz_to_time_t(TimestampTz t) ...@@ -1301,6 +1301,33 @@ timestamptz_to_time_t(TimestampTz t)
return result; return result;
} }
/*
* Produce a C-string representation of a TimestampTz.
*
* This is mostly for use in emitting messages. The primary difference
* from timestamptz_out is that we force the output format to ISO. Note
* also that the result is in a static buffer, not pstrdup'd.
*/
const char *
timestamptz_to_str(TimestampTz t)
{
static char buf[MAXDATELEN + 1];
int tz;
struct pg_tm tt,
*tm = &tt;
fsec_t fsec;
char *tzn;
if (TIMESTAMP_NOT_FINITE(t))
EncodeSpecialTimestamp(t, buf);
else if (timestamp2tm(t, &tz, tm, &fsec, &tzn, NULL) == 0)
EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
else
strlcpy(buf, "(timestamp out of range)", sizeof(buf));
return buf;
}
void void
dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec) dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/xact.h,v 1.86 2007/04/30 03:23:49 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.87 2007/04/30 21:01:53 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -81,7 +81,7 @@ typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid, ...@@ -81,7 +81,7 @@ typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,
typedef struct xl_xact_commit typedef struct xl_xact_commit
{ {
time_t xtime; TimestampTz xact_time; /* time of commit */
int nrels; /* number of RelFileNodes */ int nrels; /* number of RelFileNodes */
int nsubxacts; /* number of subtransaction XIDs */ int nsubxacts; /* number of subtransaction XIDs */
/* Array of RelFileNode(s) to drop at commit */ /* Array of RelFileNode(s) to drop at commit */
...@@ -93,7 +93,7 @@ typedef struct xl_xact_commit ...@@ -93,7 +93,7 @@ typedef struct xl_xact_commit
typedef struct xl_xact_abort typedef struct xl_xact_abort
{ {
time_t xtime; TimestampTz xact_time; /* time of abort */
int nrels; /* number of RelFileNodes */ int nrels; /* number of RelFileNodes */
int nsubxacts; /* number of subtransaction XIDs */ int nsubxacts; /* number of subtransaction XIDs */
/* Array of RelFileNode(s) to drop at abort */ /* Array of RelFileNode(s) to drop at abort */
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.19 2007/03/03 20:02:27 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.20 2007/04/30 21:01:53 tgl Exp $
*/ */
#ifndef XLOG_INTERNAL_H #ifndef XLOG_INTERNAL_H
#define XLOG_INTERNAL_H #define XLOG_INTERNAL_H
...@@ -71,7 +71,7 @@ typedef struct XLogContRecord ...@@ -71,7 +71,7 @@ typedef struct XLogContRecord
/* /*
* Each page of XLOG file has a header like this: * Each page of XLOG file has a header like this:
*/ */
#define XLOG_PAGE_MAGIC 0xD05F /* can be used as WAL version indicator */ #define XLOG_PAGE_MAGIC 0xD061 /* can be used as WAL version indicator */
typedef struct XLogPageHeaderData typedef struct XLogPageHeaderData
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.68 2007/04/30 03:23:49 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.69 2007/04/30 21:01:53 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -318,6 +318,8 @@ extern bool TimestampDifferenceExceeds(TimestampTz start_time, ...@@ -318,6 +318,8 @@ extern bool TimestampDifferenceExceeds(TimestampTz start_time,
extern TimestampTz time_t_to_timestamptz(time_t tm); extern TimestampTz time_t_to_timestamptz(time_t tm);
extern time_t timestamptz_to_time_t(TimestampTz t); extern time_t timestamptz_to_time_t(TimestampTz t);
extern const char *timestamptz_to_str(TimestampTz t);
extern int tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt); extern int tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt);
extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm,
fsec_t *fsec, char **tzn, pg_tz *attimezone); fsec_t *fsec, char **tzn, pg_tz *attimezone);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment