How to detect if a PostgreSQL slave is consistent up to a known transaction on the master?

StackOverflow https://stackoverflow.com/questions/22889348

  •  28-06-2023
  •  | 
  •  

Question

I am working out a master/slave architecture for my web application in which frontends reading from slaves must only do so if the slave is consistent up to the time of the last known write triggered by the requesting client. Slaves can be inconsistent with respect to the master as long as they are inconsistent only regarding writes by other users, not by the requesting user.

All writes are sent to the master which is easy enough, but the trick is knowing when to send reads to the master versus a slave.

What I would like to do is:

  • On a write request, at the end of the request processing phase after all writes are committed, take some kind of reading of the database's current transaction pointer and stash it in a cookie on the client response.

  • On a read request, take the value from this cookie and first check if the slave is caught up to this transaction pointer location. If it's caught up, delete the cookie and read from the slave happily. If not, read from the master and leave the cookie in place.

I am not sure what specific functions to use to achieve this on the master and slave or if they exist at all. I would like to avoid the overhead of a dedicated counter in a table that I have to explicitly update and query, since I presume PG is already doing this for me in some fashion. However, I could do that if necessary.

pg_current_xlog_location on the master and pg_last_xlog_replay_location on the slave look promising, however, I do not know enough to know if these will reliably do the job:

  • Will an idle master and a caught-up slave always report the exact same values for these functions?

  • The syntax of their return value is confusing to me, for instance 0/6466270 - how do I convert this string into an integer in a way that I can reliably do a simple greater- or less-than comparison?

Note: I am planning to use streaming replication with slaves in hot standby mode, if that affects the available solutions. I am currently using 9.1, but would entertain an upgrade if that helped.

Was it helpful?

Solution

take some kind of reading of the database's current transaction pointer and stash it in a cookie on the client response.

You can use:

SELECT pg_xlog_location_diff(pg_current_xlog_location(), '0/00000000');

to get an absolute position, but in this case you actually only need to store pg_current_xlog_location(), because:

On a read request, take the value from this cookie and first check if the slave is caught up to this transaction pointer location.

Compare the saved pg_current_xlog_location() with the slave's pg_last_xlog_replay_location() using pg_xlog_location_diff.

Will an idle master and a caught-up slave always report the exact same values for these functions?

If you're using streaming replication, yes. If you're doing archive based replication, no.

You shouldn't rely on the same value anyway. You just need to know if the slave is new enough.

The syntax of their return value is confusing to me, for instance 0/6466270 - how do I convert this string into an integer in a way that I can reliably do a simple greater- or less-than comparison?

Use pg_xlog_location_diff. It might not be in 9.1, so you may need to upgrade.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top