On 17/09/10 12:10, Dimitri Fontaine wrote:
Heikki Linnakangas<heikki.linnakan...@enterprisedb.com>  writes:
* Support multiple standbys with various synchronization levels.

* What happens if a synchronous standby isn't connected at the moment?
Return immediately vs. wait forever.

* Per-transaction control. Some transactions are important, others are not.

* Quorum commit. Wait until n standbys acknowledge. n=1 and n=all servers
can be seen as important special cases of this.

* async, recv, fsync and replay levels of synchronization.

So what should the user interface be like? Given the 1st and 2nd
requirement, we need standby registration. If some standbys are important
and others are not, the master needs to distinguish between them to be able
to determine that a transaction is safely delivered to the important
standbys.

Well the 1st point can be handled in a distributed fashion, where the
sync level is setup at the slave.

If the synchronicity is configured in the standby, how does the master know that there's a synchronous slave out there that it should wait for, if that slave isn't connected at the moment?

OTOH, if we do want fine-grained per-transaction control, a simple boolean
or even an enum GUC doesn't really cut it. For truly fine-grained control
you want to be able to specify exceptions like "wait until this is replayed
in slave named 'reporting'" or 'don't wait for acknowledgment from slave
named 'uk-server'". With standby registration, we can invent a syntax for
specifying overriding rules in the transaction. Something like SET
replication_exceptions = 'reporting=replay, uk-server=async'.

Then you want to be able to have more than one reporting server and need
only one of them at the "replay" level, but you don't need to know which
it is. Or on the contrary you have a failover server and you want to be
sure this one is at the replay level whatever happens.

Then you want topology flexibility: you need to be able to replace a
reporting server with another, ditto for the failover one.

Did I tell you my current thinking on how to tackle that yet? :) Using a
distributed setup, where each slave has a weight (several votes per
transaction) and a level offering would allow that I think.

Yeah, the quorum stuff. That's all good, but doesn't change the way you would do per-transaction control. By specifying overrides on a per-transaction basis, you can have as fine-grained control as you possibly can. Anything you can specify in a configuration file can then also be specified per-transaction with overrides. The syntax just needs to be flexible enough.

If we buy into the concept of per-transaction exceptions, we can put that issue aside for the moment, and just consider how to configure things in a config file. Anything you can express in the config file can also be expressed per-transaction with the exceptions GUC.

Now something similar to your idea that I can see a need for is being
able to have a multi-part quorum target: when you currently say that you
want 2 votes for sync, you would be able to say you want 2 votes for
recv, 2 for fsync and 1 for replay. Remember that any slave is setup to
offer only one level of synchronicity but can offer multiple votes.

How this would look like in the setup? Best would be to register the
different service levels your application need. Time to bikeshed a
little?

   sync_rep_services = {critical: recv=2, fsync=2, replay=1;
                        important: fsync=3;
                        reporting: recv=2, apply=1}

Well you get the idea, it could maybe get stored on a catalog somewhere
with nice SQL commands etc. The goal is then to be able to handle a much
simpler GUC in the application, sync_rep_service = important for
example. Reserved label would be off, the default value

So ignoring the quorum stuff for a moment, the general idea is that you have predefined sets of configurations (or exceptions to the general config) specified in a config file, and in the application you just choose among those with "sync_rep_service=XXX". Yeah, I like that, it allows you to isolate the details of the topology from the application.

If you add a weight to each slave then a quorum commit, you don't change
the implementation complexity and you offer lot of setup flexibility. If
the slave sync-level and weight are SIGHUP, then it even become rather
easy to switch roles online or to add new servers or to organise a
maintenance window — the quorum to reach is a per-transaction GUC on the
master, too, right?

I haven't bought into the quorum idea yet, but yeah, if we have quorum support, then it would be configurable on a per-transaction basis too with the above mechanism.

--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to