mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Add function pg_xlog_location_diff to help comparisons
Comparing two xlog locations are useful for example when calculating replication lag. Euler Taveira de Oliveira, reviewed by Fujii Masao, and some cleanups from me
This commit is contained in:
parent
0e5e167aae
commit
bc5ac36865
@ -14475,11 +14475,15 @@ SELECT set_config('log_statement_stats', 'off', false);
|
|||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>pg_xlogfile_name_offset</primary>
|
<primary>pg_xlogfile_name_offset</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>pg_xlog_location_diff</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The functions shown in <xref
|
The functions shown in <xref
|
||||||
linkend="functions-admin-backup-table"> assist in making on-line backups.
|
linkend="functions-admin-backup-table"> assist in making on-line backups.
|
||||||
These functions cannot be executed during recovery.
|
These functions cannot be executed during recovery (except
|
||||||
|
<function>pg_xlog_location_diff</function>).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<table id="functions-admin-backup-table">
|
<table id="functions-admin-backup-table">
|
||||||
@ -14547,6 +14551,13 @@ SELECT set_config('log_statement_stats', 'off', false);
|
|||||||
<entry><type>text</>, <type>integer</></entry>
|
<entry><type>text</>, <type>integer</></entry>
|
||||||
<entry>Convert transaction log location string to file name and decimal byte offset within file</entry>
|
<entry>Convert transaction log location string to file name and decimal byte offset within file</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<literal><function>pg_xlog_location_diff(<parameter>location</> <type>text</>, <parameter>location</> <type>text</>)</function></literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>numeric</></entry>
|
||||||
|
<entry>Calculate the difference between two transaction log locations</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
@ -14639,6 +14650,13 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
|
|||||||
needs to be archived.
|
needs to be archived.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<function>pg_xlog_location_diff</> calculates the difference in bytes
|
||||||
|
between two transaction log locations. It can be used with
|
||||||
|
<structname>pg_stat_replication</structname> or some functions shown in
|
||||||
|
<xref linkend="functions-admin-backup-table"> to get the replication lag.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For details about proper usage of these functions, see
|
For details about proper usage of these functions, see
|
||||||
<xref linkend="continuous-archiving">.
|
<xref linkend="continuous-archiving">.
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "replication/walreceiver.h"
|
#include "replication/walreceiver.h"
|
||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/numeric.h"
|
||||||
#include "utils/guc.h"
|
#include "utils/guc.h"
|
||||||
#include "utils/timestamp.h"
|
#include "utils/timestamp.h"
|
||||||
|
|
||||||
@ -465,3 +466,92 @@ pg_is_in_recovery(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
PG_RETURN_BOOL(RecoveryInProgress());
|
PG_RETURN_BOOL(RecoveryInProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate the text form of a transaction log location.
|
||||||
|
* (Just using sscanf() input allows incorrect values such as
|
||||||
|
* negatives, so we have to be a bit more careful about that).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
validate_xlog_location(char *str)
|
||||||
|
{
|
||||||
|
#define MAXLSNCOMPONENT 8
|
||||||
|
|
||||||
|
int len1,
|
||||||
|
len2;
|
||||||
|
|
||||||
|
len1 = strspn(str, "0123456789abcdefABCDEF");
|
||||||
|
if (len1 < 1 || len1 > MAXLSNCOMPONENT || str[len1] != '/')
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for transaction log location: \"%s\"", str)));
|
||||||
|
|
||||||
|
len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
|
||||||
|
if (len2 < 1 || len2 > MAXLSNCOMPONENT || str[len1 + 1 + len2] != '\0')
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for transaction log location: \"%s\"", str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the difference in bytes between two WAL locations.
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
pg_xlog_location_diff(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
text *location1 = PG_GETARG_TEXT_P(0);
|
||||||
|
text *location2 = PG_GETARG_TEXT_P(1);
|
||||||
|
char *str1,
|
||||||
|
*str2;
|
||||||
|
XLogRecPtr loc1,
|
||||||
|
loc2;
|
||||||
|
Numeric result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read and parse input
|
||||||
|
*/
|
||||||
|
str1 = text_to_cstring(location1);
|
||||||
|
str2 = text_to_cstring(location2);
|
||||||
|
|
||||||
|
validate_xlog_location(str1);
|
||||||
|
validate_xlog_location(str2);
|
||||||
|
|
||||||
|
if (sscanf(str1, "%X/%X", &loc1.xlogid, &loc1.xrecoff) != 2)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
|
errmsg("could not parse transaction log location \"%s\"", str1)));
|
||||||
|
if (sscanf(str2, "%X/%X", &loc2.xlogid, &loc2.xrecoff) != 2)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
|
errmsg("could not parse transaction log location \"%s\"", str2)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity check
|
||||||
|
*/
|
||||||
|
if (loc1.xrecoff > XLogFileSize)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
|
errmsg("xrecoff \"%X\" is out of valid range, 0..%X", loc1.xrecoff, XLogFileSize)));
|
||||||
|
if (loc2.xrecoff > XLogFileSize)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
|
errmsg("xrecoff \"%X\" is out of valid range, 0..%X", loc2.xrecoff, XLogFileSize)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* result = XLogFileSize * (xlogid1 - xlogid2) + xrecoff1 - xrecoff2
|
||||||
|
*/
|
||||||
|
result = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
|
||||||
|
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) loc1.xlogid)),
|
||||||
|
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) loc2.xlogid))));
|
||||||
|
result = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
|
||||||
|
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) XLogFileSize)),
|
||||||
|
NumericGetDatum(result)));
|
||||||
|
result = DatumGetNumeric(DirectFunctionCall2(numeric_add,
|
||||||
|
NumericGetDatum(result),
|
||||||
|
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) loc1.xrecoff))));
|
||||||
|
result = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
|
||||||
|
NumericGetDatum(result),
|
||||||
|
DirectFunctionCall1(int8_numeric, Int64GetDatum((int64) loc2.xrecoff))));
|
||||||
|
|
||||||
|
PG_RETURN_NUMERIC(result);
|
||||||
|
}
|
||||||
|
@ -281,5 +281,6 @@ extern Datum pg_is_in_recovery(PG_FUNCTION_ARGS);
|
|||||||
extern Datum pg_xlog_replay_pause(PG_FUNCTION_ARGS);
|
extern Datum pg_xlog_replay_pause(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_xlog_replay_resume(PG_FUNCTION_ARGS);
|
extern Datum pg_xlog_replay_resume(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_is_xlog_replay_paused(PG_FUNCTION_ARGS);
|
extern Datum pg_is_xlog_replay_paused(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum pg_xlog_location_diff(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
#endif /* XLOG_INTERNAL_H */
|
#endif /* XLOG_INTERNAL_H */
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201203031
|
#define CATALOG_VERSION_NO 201203041
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2936,6 +2936,9 @@ DESCR("xlog filename and byte offset, given an xlog location");
|
|||||||
DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ pg_xlogfile_name _null_ _null_ _null_ ));
|
DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ pg_xlogfile_name _null_ _null_ _null_ ));
|
||||||
DESCR("xlog filename, given an xlog location");
|
DESCR("xlog filename, given an xlog location");
|
||||||
|
|
||||||
|
DATA(insert OID = 3165 ( pg_xlog_location_diff PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1700 "25 25" _null_ _null_ _null_ _null_ pg_xlog_location_diff _null_ _null_ _null_ ));
|
||||||
|
DESCR("difference in bytes, given two xlog locations");
|
||||||
|
|
||||||
DATA(insert OID = 3809 ( pg_export_snapshot PGNSP PGUID 12 1 0 0 0 f f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_export_snapshot _null_ _null_ _null_ ));
|
DATA(insert OID = 3809 ( pg_export_snapshot PGNSP PGUID 12 1 0 0 0 f f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_export_snapshot _null_ _null_ _null_ ));
|
||||||
DESCR("export a snapshot");
|
DESCR("export a snapshot");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user