Tom Lane wrote:

Andrew Dunstan <[EMAIL PROTECTED]> writes:


How about (even quicker and dirtier) putting a limited loop (say 5 iterations?) with a small delay in it around the check for whether or not we are the only connection? Createdb is hardly a time critical operation, and taking a few seconds extra in the worst case wouldn't matter that much, would it?



Hmm, that might help, though as you say it's only a 90% solution.


It occurs to me that it wouldn't really be that hard to develop a
locking-based solution, if we consider that the purpose of the lock
is to keep new connections out of the template database.  Let's assume
we define a lock tag that represents a whole database (dbId = db's OID,
relId = zero would probably do).  Modify the backend so that every
session takes a share-lock on this tag during its startup sequence
(early in ReverifyMyDatabase() would likely be a good place).  The lock
does not need to be held over the life of the session, just acquired
before any database write can possibly occur in the session.  That means
we don't need any complicated new support in the lock manager.

Now, we can make CREATE DATABASE (and DROP DATABASE) acquire exclusive
lock on this lock before they look for extant sessions attached to the
target database.  That prevents any new sessions from getting in.  In
the CREATE case, incoming sessions for the template database are simply
delayed until the CREATE completes.  In the DROP case, incoming sessions
for the doomed database are guaranteed to notice that their database is
gone, because they won't be able to look for it in pg_database until
after the DROP completes.  (I think we currently guarantee the latter
by means of DROP taking an exclusive lock on pg_database, but a lock
that didn't lock out unrelated operations would surely be nicer.)

We could combine this with your idea of delaying: after acquiring the
exclusive lock, CREATE can delay to see if existing sessions connected
to the template database quit soon.  Since the exclusive lock is
preventing new sessions from coming in, this delay does not need to be
very long (probably the average length of a CREATE DATABASE operation
would be enough).

Thoughts?




Neat. Took me a few minutes to get my head around how it would work. Seems like any success would be guaranteed to be correct, which is a definite advance, and only long-lived connections to the template (e.g. "psql template1") would cause failures. A delay of around 2 secs seems right on my system.


(I played around in my head with other ideas like a read-only connection flag and things based on checksumming, but they either seemed likely to be error-prone or too expensive.)

cheers

andrew


---------------------------(end of broadcast)--------------------------- TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faqs/FAQ.html

Reply via email to