PostgreSQL 10 or later (answer)
For postgresql 10 or later (function pg_last_xlog_receive_location()
and others does not exist in this version), I use this:
SELECT
pg_is_in_recovery() AS is_slave,
pg_last_wal_receive_lsn() AS receive,
pg_last_wal_replay_lsn() AS replay,
pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() AS synced,
(
EXTRACT(EPOCH FROM now()) -
EXTRACT(EPOCH FROM pg_last_xact_replay_timestamp())
)::int AS lag;
if you run this query on master, the results will be:
is_slave | receive | replay | synced | lag
----------+---------+--------+--------+-----
f | | | |
(1 row)
if you run this query on synced slave, the results will be like:
is_slave | receive | replay | synced | lag
----------+-----------+-----------+--------+-----
t | 0/3003128 | 0/3003128 | t | 214
(1 row)
if you run this query on NOT synced slave, the results will be like:
is_slave | receive | replay | synced | lag
----------+-----------+-----------+--------+-----
t | 0/30030F0 | 0/30023B0 | f | 129
(1 row)
NOTE: lag
(seconds) has a special meaning here (it is not the same that replay_lag
/write_lag
/flush_lag
from pg_stat_replication
view) and it is only useful when synced
column is false
, because lag
means how many seconds elapsed since the last action was commited. In a low traffic site, this value is useless. But in an high traffic site, synced
could (and will) be almost of time false
, however if it has lag
value small enough that server could be considered synced.
So, in order to discovery if that server is synced, I check (in this order):
- IF
is_slave
is f
(meaning that is a not a slave, maybe a master, so it is synced);
- IF
synced
is t
(meaning that is a synced slave, so it is synced);
- IF (supposing applicable)
lag <= :threshold:
(meaning that is not a synced slave, but it is not too far from master, so it's synced enough for me).
If you want lag in seconds including decimals, do:
SELECT
pg_is_in_recovery() AS is_slave,
pg_last_wal_receive_lsn() AS receive,
pg_last_wal_replay_lsn() AS replay,
pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() AS synced,
EXTRACT(SECONDS FROM now() - pg_last_xact_replay_timestamp())::float AS lag;