Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1aVr1h-0003dz-1i for pgsql-hackers@arkaria.postgresql.org; Wed, 17 Feb 2016 01:35:33 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84) (envelope-from ) id 1aVr1f-0004JS-T4 for pgsql-hackers@arkaria.postgresql.org; Wed, 17 Feb 2016 01:35:31 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84) (envelope-from ) id 1aVr0J-0002dj-IK for pgsql-hackers@postgresql.org; Wed, 17 Feb 2016 01:34:07 +0000 Received: from mail-lf0-x236.google.com ([2a00:1450:4010:c07::236]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84) (envelope-from ) id 1aVr0A-0004E5-6K for pgsql-hackers@postgresql.org; Wed, 17 Feb 2016 01:34:06 +0000 Received: by mail-lf0-x236.google.com with SMTP id j78so1198804lfb.1 for ; Tue, 16 Feb 2016 17:33:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=aqbdRWC+E9WIXiQkUn8l2Ch9ofQGJzMji695IO6No9E=; b=MWbM3Se3gNYWamQ4dsKZWjfOP26r+xuRaP6yV57vROFMXi2Oub2HVekJZ0iic3SY2X olJDG2ZjwmMqZQiDdVTlVJR4SlFro1KlnqeBeTl1P6YufxOXLvAFjxs4sw3ChD5XQgCw G5082uuZxzj8LNMc9XpW17cIqhQvVNLOose2fmBPKYivj6ZAxzw4FQvGqQIc0zuYQye7 +MZ1rG7PnO7tkq7qpIYNKKKzitlO44dbQjcXQ11bqSYsA/vdCvBdXuldolMKiZpgCS56 vVXTZLH65Ox35bKviJF3jwwwlB4sWK6q4qDzCBGzElEuIHGpLfTj6g+CuWV+ndfCiO06 JT1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=aqbdRWC+E9WIXiQkUn8l2Ch9ofQGJzMji695IO6No9E=; b=mi5QjQJqIIxVd9Md1cTkQfNYL/obGnOV4J6LxoHB4OlTynkSS/LRjmq3EDbvT0ZqHG L3wPDFCNgIs35Ht5G0RYkW6nyD7o35BpUOTCWymLBdB/drE0bO0E/9F6LJ2xI556grUC 1IXiAu4LVRiZSAe0qQgwgUPnlr+aYX8a23z05bBYmll7yxkIOIhEGr6eOrVKT0HJYGkU RSSHCbitQ+B0zws///5dg9nz3un1HcwJ6y6vAHq9rWju9HZM6bRmnYxSijqYVccsTgey 2L+TQa1HJY6dc0ceXn7/vXN9W0Jnqhstx1zKkPfmivpCjPFtsAhN6YXXi+kFMhnpJk7W ClbA== X-Gm-Message-State: AG10YORrAmZ36yibwhXadmxEFMbpYbf9UoSn1VNZe6Obwmpot8E0HULjsPcMC3sT1fI3RJ93m+ZOWl7m8gCo+KD4 MIME-Version: 1.0 X-Received: by 10.25.147.202 with SMTP id v193mr2722101lfd.162.1455672837104; Tue, 16 Feb 2016 17:33:57 -0800 (PST) Received: by 10.114.201.225 with HTTP; Tue, 16 Feb 2016 17:33:56 -0800 (PST) In-Reply-To: References: <5685BB86.5010901@2ndquadrant.com> <56A84422.2030309@commandprompt.com> <20160216143820.GC31273@momjian.us> Date: Wed, 17 Feb 2016 09:33:56 +0800 Message-ID: Subject: Re: pglogical - logical replication contrib module From: Craig Ringer To: obartunov@gmail.com Cc: Bruce Momjian , "Joshua D. Drake" , Petr Jelinek , PostgreSQL-development Content-Type: multipart/alternative; boundary=001a1140225c5d8699052bed3e83 X-Pg-Spam-Score: -2.6 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org --001a1140225c5d8699052bed3e83 Content-Type: text/plain; charset=UTF-8 On 17 February 2016 at 00:54, Oleg Bartunov wrote: > > DDL support is what it's missed for now. > > TBH, based on experience with DDL replication and deparse in BDR, it's going to be missing for a while yet too, or at least not comprehensively present without caveats or exceptions. Some DDL operations don't translate well to a series of replicatable actions. The case I hit the most is ALTER TABLE mytable ADD COLUMN somecolumn sometype NOT NULL DEFAULT some_function(); This is executed (simplified) by taking an ACCESS EXCLUSIVE lock, changing the catalogs but not making the changes visible yet, rewriting the table, and committing to make the rewritten table and the catalog changes visible. That won't work well with logical replication. We currently capture DDL with event triggers and log them to a table for later logical decoding and replay - that's the "recognised" way. The trouble being that replaying that statement will result in an unnecessary full table rewrite on the downstream. Then we have to decode and send stream of changes to a table called pg_temp_, truncate the copy of mytable on the downstream that we just rewrote and apply those rows instead. Of course all that only works sensibly if you have exactly one upstream and the downstream copy of the table is treated as (or enforced as) read-only. Improving this probably needs DDL deparse to be smarter. Rather than just emitting something that can be reconstructed into the SQL text of the DDL it needs to emit one or more steps that are semantically the same but allow us to skip the rewrite. Along the lines of: * ALTER TABLE mytable ADD COLUMN somecolumn sometype; * ALTER TABLE mytable ALTER COLUMN somecolumn DEFAULT some_function(); * * ALTER TABLE mytable ALTER COLUMN somecolumn NOT NULL; Alternately the downstream would need a hook that lets it intercept and prevent table rewrites caused by ALTER TABLE and similar. So it can instead just do a truncate and wait for the new rows to come from the master. Note that all this means the standby has to hold an ACCESS EXCLUSIVE lock on the table during all of replay. That shouldn't be necessary, all we really need is an EXCLUSIVE lock since concurrent SELECTs are fine. No idea how to do that. Deparse is also just horribly complicated to get right. There are so many clauses and subclauses and variants of statements. Each of which must be perfect. Not everything has a simple and obvious mapping on the downstream side either. TRUNCATE ... CASCADE is the obvious one. You do a cascade truncate on the master - do you want that to replicate as a cascaded truncate on the replica, or a truncate of only those tables that actually got truncated on the master? If the replica has additional tables with FKs pointing at tables replica the TRUNCATE would truncate those too if you replicate it as CASCADE; if you don't the truncate will fail instead. Really, both are probably wrong as far as the user is concerned, but we can't truncate just the tables truncated on the master, ignore the FK relationships, and leave dangling FK references either. All this means that DDL replication is probably only going to make sense in scenarios where there's exactly one master and the replica obeys some rules like "don't create FKs pointing from non-replicated tables to tables replicated from somewhere else". A concept we currently have no way to express or enforce like we do persistent-to-UNLOGGED FKs. Then there's global objects. Something as simple as: CREATE ROLE fred; CREATE TABLE blah(...) OWNER fred; will break replication because we only see the CREATE TABLE, not the CREATE ROLE. If we instead replayed the CREATE ROLE and there were multiple connections between different DBs on an upstream and downstream apply would fail on all but one. But we can't anyway since there's no way to capture that CREATE ROLE from any DB except the one it was executed in, which might not even be one of the ones doing replication. I strongly suspect we'll need logical decoding to be made aware of such global DDL and decode it from the WAL writes to the system catalogs. Which will be fun - but at least modifications to the shared catalogs are a lot simpler than the sort of gymnastics done by ALTER TABLE, etc. -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services --001a1140225c5d8699052bed3e83 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
On 1= 7 February 2016 at 00:54, Oleg Bartunov <obartunov@gmail.com> wrote:
=C2=A0
=

DDL support is what it's missed for now.

=

TBH, based on experience with = DDL replication and deparse in BDR, it's going to be missing for a whil= e yet too, or at least not comprehensively present without caveats or excep= tions.


Some DDL operations don'= t translate well to a series of replicatable actions. The case I hit the mo= st is

=C2=A0 =C2=A0ALTER TABLE mytable ADD COLUMN = somecolumn sometype NOT NULL DEFAULT some_function();

<= div>This is executed (simplified) by taking an ACCESS EXCLUSIVE lock, chang= ing the catalogs but not making the changes visible yet, rewriting the tabl= e, and committing to make the rewritten table and the catalog changes visib= le.

That won't work well with logical replicat= ion. We currently capture DDL with event triggers and log them to a table f= or later logical decoding and replay - that's the "recognised"= ; way. The trouble being that replaying that statement will result in an un= necessary full table rewrite on the downstream. Then we have to decode and = send stream of changes to a table called pg_temp_<oid_of_mytable>, tr= uncate the copy of mytable on the downstream that we just rewrote and apply= those rows instead.

Of course all that only works= sensibly if you have exactly one upstream and the downstream copy of the t= able is treated as (or enforced as) read-only.

Imp= roving this probably needs DDL deparse to be smarter. Rather than just emit= ting something that can be reconstructed into the SQL text of the DDL it ne= eds to emit one or more steps that are semantically the same but allow us t= o skip the rewrite. Along the lines of:

* ALTER TA= BLE mytable ADD COLUMN somecolumn sometype;
* ALTER TABLE mytable= ALTER COLUMN somecolumn DEFAULT some_function();
* <wait for = rewrite data for mytable>
* ALTER TABLE mytable ALTER COLUMN s= omecolumn NOT NULL;

Alternately the downstream wou= ld need a hook that lets it intercept and prevent table rewrites caused by = ALTER TABLE and similar. So it can instead just do a truncate and wait for = the new rows to come from the master.

Note that al= l this means the standby has to hold an ACCESS EXCLUSIVE lock on the table = during all of replay. That shouldn't be necessary, all we really need i= s an EXCLUSIVE lock since concurrent SELECTs are fine. No idea how to do th= at.



Deparse is also = just horribly complicated to get right. There are so many clauses and subcl= auses and variants of statements. Each of which must be perfect.
=


Not everything has a simple an= d obvious mapping on the downstream side either. TRUNCATE ... CASCADE is th= e obvious one. You do a cascade truncate on the master - do you want that t= o replicate as a cascaded truncate on the replica, or a truncate of only th= ose tables that actually got truncated on the master? If the replica has ad= ditional tables with FKs pointing at tables replica the TRUNCATE would trun= cate those too if you replicate it as CASCADE; if you don't the truncat= e will fail instead. Really, both are probably wrong as far as the user is = concerned, but we can't truncate just the tables truncated on the maste= r, ignore the FK relationships, and leave dangling FK references either.


All this means that DDL replication i= s probably only going to make sense in scenarios where there's exactly = one master and the replica obeys some rules like "don't create FKs= pointing from non-replicated tables to tables replicated from somewhere el= se". A concept we currently have no way to express or enforce like we = do persistent-to-UNLOGGED FKs.



=
Then there's global objects. Something as simple as:

CREATE ROLE fred;

CREATE TABLE b= lah(...) OWNER fred;

will break replication becaus= e we only see the CREATE TABLE, not the CREATE ROLE. If we instead replayed= the CREATE ROLE and there were multiple connections between different DBs = on an upstream and downstream apply would fail on all but one. But we can&#= 39;t anyway since there's no way to capture that CREATE ROLE from any D= B except the one it was executed in, which might not even be one of the one= s doing replication.

I strongly suspect we'll = need logical decoding to be made aware of such global DDL and decode it fro= m the WAL writes to the system catalogs. Which will be fun - but at least m= odifications to the shared catalogs are a lot simpler than the sort of gymn= astics done by ALTER TABLE, etc.


<= div>
--
<= div dir=3D"ltr">=C2=A0Craig Ringer=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 http://www.2ndQuadrant= .com/
=C2=A0PostgreSQL Development, 24x7 Support, Training & Ser= vices
--001a1140225c5d8699052bed3e83--