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.

Reply via email to