On Fri, 2009-01-23 at 17:51 +0200, Heikki Linnakangas wrote:
> In ERROR mode, you don't really want to interrupt the target backend. In
> ReadBuffer, you're checking a global variable,
> BufferRecoveryConflictPending on each call, and if it's set, you check
> the buffer's LSN against the LSN of the earliest LSN conflicting LSN,
> and throw an error if it's greater than that. Why do we jump through so
> many hoops to get the earliest conflicting LSN to where it's needed? At
> the moment:
>
> 1. Startup process sets the LSN in the target backend's PGPROC entry,
> and signals it with SIGINT.
> 2. The target backend receives the signal; ProcessInterrupts is called
> either immediately or at the next CHECK_FOR_INTERRUPTS() call.
> 3. ProcessInterrupts reads the value from PGPROC, and passes it to bufmgr.c
>
> ISTM that if ReadBuffer read the value directly from the PGPROC entry,
> there would be no need for the signaling (in the ERROR mode).
That is possible and I considered it. If we did it that way we would
need to read the PGPROC each time we read a buffer. AFAICS we would need
to use a spinlock to do that since reading an XLogRecPtr would not be
atomic.
So doing it the way I've done it allows us to use a local variable which
can be more easily cached and avoids the locking overhead.
We do still need to signal anyway for the FATAL case, so we're not
significantly affecting the patch footprint by changing that.
> Correct me if I'm wrong, but I thought the idea of this new conflict
> resolution was that the startup process doesn't need to wait for the
> target backend to die. Instead, the target backend knows to commit
> suicide if it stumbles into a buffer that's been modified in a
> conflicting way. Looking at ResolveRecoveryConflictWithVirtualXIDs, it
> looks like we still wait.
err, no, that's just an oversight, not intentional.
-- Simon Riggs www.2ndQuadrant.comPostgreSQL Training, Services and Support