protocol version negotiation (Re: Libpq PGRES_COPY_BOTH - version compatibility)

From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Peter Eisentraut <peter_e(at)gmx(dot)net>, Magnus Hagander <magnus(at)hagander(dot)net>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: protocol version negotiation (Re: Libpq PGRES_COPY_BOTH - version compatibility)
Date: 2017-06-28 17:24:03
Message-ID: CA+TgmoZ3_xAZ7qdycN4nE44S-6r6-2rkdE1vn_g1RkO91dhBBA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Mon, Mar 28, 2011 at 7:07 PM, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:
> I wrote:
>> Now if we had a track record showing that we could tweak the protocol
>> version without causing problems, it'd be fine with me to do it for this
>> usage. But we don't, and this particular case doesn't seem like the
>> place to start.
>
> And, btw, a moment's study of the protocol version checking code in
> postmaster.c shows that bumping the minor version number to 3.1 *would*
> break things: a client requesting 3.1 from a current postmaster would
> get a failure.
>
> Maybe we oughta change that logic --- it's not clear to me that there's
> any meaningful difference between major and minor numbers given the
> current postmaster behavior.

I just had a conversation at Postgres Vision that reminded me of the
old thread quoted aboce, and it seems to me that what Tom said there
is a good idea. We've made quite a number of protocol version changes
over the years -- most recently, SCRAM introduced AuthenticationSASL
-- without ever bumping the protocol version. In the case of the
change that this thread was originally about, namely the introduction
of CopyBoth, it could be argued that there is no real need to bump the
protocol version, because the client initiates the use of the new
protocol message and, before doing so, can know whether the server
version is new enough to support that protocol message based on the
ParameterStatus message for server_version which is sent after
authentication is complete. Fair enough, but:

1. If we want to add a new message which is initiated by the server
rather than the client, the server currently has no way of knowing
whether the client is new enough to understand the message, because
the client never identifies itself except by submitting a protocol
version which must always be exactly 3.0 or the connection will be
killed. SCRAM itself suffers from this problem; if an older libpq
tries to connect to a v10 server, they'll get a lousy error message
unless they've got a minor release new enough to contain
96d0f988b150aa0b52b44b8c1adbc7ef59262a1a or one of its siblings.
That's not the worst problem ever, but at the same time it's not
really a good design to rely on people upgrading the clients in order
to get the correct message about the client being too old. It would
be much better if the client identified itself to the server. Then if
the server sees that the client is old, it can give the client an
appropriate error, and if the client is new enough, then it can be
sure that it will be understood.

2. If we want to add a new message is initiated by the client before
authentication is complete, ParameterStatus messages won't have been
sent yet, so the client has no idea what capabilities the server might
be able to support.

3. It's a bit unclean to use the server version as a proxy for the
wire protocol version; there are non-PostgreSQL servers which speak
the PostgreSQL wire protocol, and making them impersonate a specific
version of PostgreSQL in order to clarify which wire protocol features
they support isn't really very nice. So maybe there's a case for
bumping the minor version each time we actually change the protocol
rather than only in the cases where the client has no other method of
discovering the server version. For example, you can imagine a
connection proxy like pgpool or pgbouncer wanting to limit the client
to a particular wire protocol version -- the highest that it supports
-- while proxying to a newer server version sitting behind it. That
doesn't work if the server version is being abused as a sort of
back-door protocol version.

Here's my proposal:

- If the server receives a StartupMessage for v3.x where x > the
version it knows, instead of just slamming the connection shut, it
responds by sending some new message (let's say,
NegotiateProtocolVersion) specifying the highest protocol version it
supports.

- The client may then continue by sending a new StartupMessage with a
version with a version number that is within range.

If we had this, then bumping the minor protocol version wouldn't
require retrying connections, which among other problems generates
scary error messages in the logs; instead, they would succeed, but
with one additional round trip. That seems like it would represent a
substantial improvement over what we have now, where bumping the
protocol version is such an incredibly painful thing that we never do
it, even when we've actually broken wire protocol compatibility!

Of course, it would take a few releases before server versions that
support this mechanism were widespread, and so clients using a
hypothetical version 3.1 would still have to be prepared to retry the
whole connection, but if we use that as a reason not to make a change
of this sort then it's not clear how things ever get any better than
they are now. And it's clear that there is pent-up demand for the
ability to make minor additions to the protocol without breaking the
whole thing - see
https://www.postgresql.org/message-id/1318235405.31687.0.camel%40fsopti579.F-Secure.com
and https://wiki.postgresql.org/wiki/Todo#Wire_Protocol_Changes_.2F_v4_Protocol
- and while it's not clear that all of those ideas are good ones, some
of them probably are, and even if by some remote chance all of the
people who suggested them are all dead wrong, there will be more
things suggested in the future. We shouldn't wait until our back is
totally against the wall before we introduce some mechanism here that
is better than what we have today. I'm not really keen on trying to
introduce a v4 protocol any time soon, but I really like the idea of
having a reasonably low-pain way to introduce a v3.1 that adds modest
new capabilities.

Thoughts, better ideas?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2017-06-28 17:31:27 Re: Reducing pg_ctl's reaction time
Previous Message Tom Lane 2017-06-28 14:26:45 Re: building Postgresql-9.0.10 with patching MERGE keyword