Em 02-11-2017 13:40, Jeremy Evans escreveu:
On Thursday, November 2, 2017 at 12:39:55 PM UTC+1, Rodrigo Rosenfeld
Rosas wrote:
I'm not sure I understand your proposal. I don't usually know the
mapping. The oids are usually figured out by Sequel itself when I
register a row type by name, for example. This is performed during
initialization. I don't know the oids in advance. But even if I
knew, I guess you suggested that I should perform some web request
to instruct the application to run the code above. That isn't
practical if you're running a cluster of servers because you can't
guarantee that the request will be redirected to all servers in
the cluster.
Sequel obviously can figure out the type OID from the type name.
Review the related Sequel code for how to do that.
I actually tried to understand how it worked by looking at Sequel's code
yesterday but after a few minutes trying to understand it I found it to
be too confusing and gave up :)
It isn't that complicated, though I admit it's not simple either. If
you expect a database upgrade during the running life of the
application, then at startup, connect to both the old and new
databases, and get the OIDs. If you don't currently have the ability,
build it. But it needs to be done on initialization and not while the
program is running.
Either I didn't understand your suggestion or you didn't understand the
use case I'm trying to improve. So let me explain what my goal is.
Currently we have quite a few clients depending on the application.
Coordinating a scheduled maintenance window is a complicated and lengthy
process as I have to check with both my employer (which would certainly
prefer to avoid any upgrades for years or as long as possible) and with
its clients and some of them have very rigid rules for such maintenances
involving downtime. Also, I'd usually have to work in weekends or at
night when they accept a maintenance window. As you can probably guess,
I much prefer spend much more time figuring out how to reduce the
downtime as much as possible then trying to orchestrate a planned
migration downtime window.
For regular tasks, I can deploy many times a day without any downtime by
performing blue-green (canary) deployments. However, upgrading the
database is one of those tasks that I can't do without any downtime yet.
This time I got so close to this that I decided to perform the upgrade
without requesting for the maintenance window because it would take just
a few seconds of downtime and then I could afford dealing with eventual
errors that would happen in that small window if any. It wouldn't cause
anything critical, except that the user would have to retry their
operation just like it would be the case if their Internet had a
temporary connection issue.
But I'd prefer to keep the window as short as possible. By using
pglogical, I was able to get PG10 in sync with PG96 in such a way that
when I stop PG96, PG10 would have the latest data and I could then
restart PG10 in the production port. All of that would take about just
1s in our production environment. So far so great, however due to this
problem with OIDs I also have to restart the application apps dealing
with the database (the main app, the admin app and the sidekiq cluster).
Restarting those apps will add a few extra seconds to the downtime
window and if some user would try to load the application while it's
been restarted it would get an error page from nginx which I'd really
prefer to avoid at all if possible to avoid having to explain to someone
sending that nginx error page screenshot by e-mail.
Sometimes I'd need to restart PostgreSQL and that's why we setup Sequel
to always verify if the connection is valid before using it to avoid
errors in production when the database was restarted due to some change
to postgresql.conf for example. If I was able to set up the application
so that it would fix itself when the database is upgraded that would be
awesome even if it would add some overhead to the application.
Server-side performance is barely a concern in our application after
all. Keeping the app working all the time is much more of a concern just
like keeping the dependencies up to date as much as possible.
I know there are some PG load balancer solutions that allow one to start
enqueueing new requests to connections so that the database could be
restarted and then the load balancer could resume its operation and
return the connections from the queue without the user noticing the
database has restarted or upgraded. Except for this issue with OIDs
changing over upgrades. Another solution would be to keep the same OIDs
when upgrading if possible. Is it possible to keep the same OIDs when
upgrading?
I was thinking in another kind of solution. For example, when we
call DB.register_row_type, it could remember that call somewhere
and then, once it finds an OID in the result set that is not
mapped yet, it could try to check if the OIDs for the previously
registered types have changed and then re-register them. It seems
that for some reason JSON columns also stopped working after the
upgrade, so maybe the OID is not a well known value for them
either. In that case, Sequel would have to retry registering such
extensions too each time an OID mapping is not found. I understand
this is usually not desired, but it could be useful. Maybe in that
mode we could get a warning message whenever an OID is not
registered, which would be triggering such an update code. This
way we would be able to try to register all used OIDs so that they
would be usually all mapped, avoiding the re-registering of OIDs.
Not sure if this is really feasible as I don't really understand
the internals of OIDs and how they are handled by Sequel.
Not really feasible, as you will see if you review the code related
code. Sequel does a type name -> OID query, and you don't have a type
name, only a new OID.
That's why I said Sequel would have to record those attempts to get the
id from names so that it could replay it another time when some oid
mapping is missing. It would have to keep a list of names already
resolved so that it could remap them.
Plus it is common in Sequel to not have OID conversion procs
registered for types actively used, since that is faster for string
types. You would have to differentiate those OIDs from the OIDs you
care about and want to convert.
I understand but in such scenario I'd probably have to explicitly map
such common types as well, like string. Even if the performance wouldn't
be as great I don't think it would be significantly worse and I'd be
fine with the extra mili-second it would take if all that much.
Even if you could get it to work, it would likely be subject to race
conditions.
It would be fine if a few requests would be affected by some race
condition during the upgrade. Much better than seeing some proxy error
page from nginx in my case. ;)
I hope you understand my concerns with upgrading the database :)
Best,
Rodrigo.
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.