Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nMBJU-0007VH-EX for pgsql-hackers@arkaria.postgresql.org; Mon, 21 Feb 2022 16:13:24 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nMBJT-0005py-3W for pgsql-hackers@arkaria.postgresql.org; Mon, 21 Feb 2022 16:13:23 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nMB0l-0002Fa-CU for pgsql-hackers@lists.postgresql.org; Mon, 21 Feb 2022 15:54:03 +0000 Received: from mail-oi1-x22e.google.com ([2607:f8b0:4864:20::22e]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1nMB0d-0000LI-Tl for pgsql-hackers@lists.postgresql.org; Mon, 21 Feb 2022 15:54:02 +0000 Received: by mail-oi1-x22e.google.com with SMTP id j2so11288780oie.7 for ; Mon, 21 Feb 2022 07:53:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:from:date:message-id:subject:to :content-transfer-encoding; bh=f84OYn7NZZx6N7ejZrxHswB0YcutT2gBSgkqm0KR0cc=; b=E/Jop4+T7g+akMkJ364fT9oyMeP9yxWLXfA9rACG61AGyUMgkrgllqqd4pNegxGFkp FAn+vhgHLb9VZYRBuW3ojswQnZuiK4sZpw+5dk1bc8HAinwqSquv+Nhj3Q9792bSxKI9 a3XU/frT1pM/AjOGWr3gsM1LwKHNkDQ7XIlj4oHJ/p+Skw92Xalg5U2Vr5US0sldv2b0 S0yoEm2QPPbaFtGwJHn/auv3Vmi0J/k68L1n7aW8p9eMzTt/jgSZMmCmpzdIkTWNMk2U r8ttwRNpYqIvLwE3U+xPCE0SJUr9/cA0xaAqpyfycJpIJyVX04zSb+J+v++fs0VnrrSA G82w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to :content-transfer-encoding; bh=f84OYn7NZZx6N7ejZrxHswB0YcutT2gBSgkqm0KR0cc=; b=1EtYEvGCqFBmT8AkMDzOXDS1Qu76//hCyS1/EgjkTRd031XqV3pJ2+D49AANOPFYuy J23SvtnSZvJZ45wvARdVRSpXHwICx4z12Osrh2cgU+hLihFqyu61QrxIRP1eBU/ZAmEU nXV2jng4LDSlWa782G7VKrVWvZ5i/pWkeG3LwFi9o0kpYsFxLR10hkfukIHdY75PtT0E hoFGOLPQqj/gaM1Sij3xwFKebd8U9g38dVnpxdzYC/YFjckvFonCZ01V6k+PAVIuA3k+ BVfwvFIw4VUeYgHtkhhgZv2AROBMUOWk58JlXcWWHKYT5f5Hw9QVMok0ScaIq9r5ThKU TKgw== X-Gm-Message-State: AOAM530HD20o9k/F7cFV6XFLqjS25+FQNLw2xrv8zJM1Ka7LWrwIF+hB HtlSV0zBn2zcGGTc/paNrnL1g9WLY7eb0qnquZ67oxBW X-Google-Smtp-Source: ABdhPJz2KxZRri3emKca/Rgnl2oN+3SREPNM4KPq0TQMyk2n9zVIqiiv1Tho1wf9iv0e3UZ8XGGoO8oQzMcFJHbf67w= X-Received: by 2002:a05:6808:f93:b0:2d4:f855:aadd with SMTP id o19-20020a0568080f9300b002d4f855aaddmr2898841oiw.21.1645458833805; Mon, 21 Feb 2022 07:53:53 -0800 (PST) MIME-Version: 1.0 From: Zheng Li Date: Mon, 21 Feb 2022 10:53:43 -0500 Message-ID: Subject: Support logical replication of DDLs To: pgsql-hackers@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hello, One of the most frequently requested improvements from our customers is to reduce downtime associated with software updates (both major and minor versions). To do this, we have reviewed potential contributions to improving logical replication. I=E2=80=99m working on a patch to support logical replication of data definition language statements (DDLs). This is a useful feature when a database in logical replication has lots of tables, functions and other objects that change over time, such as in online cross major version upgrade. I put together a prototype that replicates DDLs using the generic messages for logical decoding. The idea is to log the candidate DDL string in ProcessUtilitySlow() using LogLogicalMessge() with a new flag in WAL record type xl_logical_message indicating it=E2=80=99s a DDL message. The xl_logical_message record is decoded and sent to the subscriber via pgoutput. The logical replication worker process is dispatched for this new DDL message type and executes the command accordingly. However, there are still many edge cases to sort out because not every DDL statement can/should be replicated. Some of these include: 1. DDL involving multiple tables where only some tables are replicated, e.g= . DROP TABLE replicated_foo, notreplicated_bar; This statement will fail on the subscriber and block logical replication. It can be detected and filtered on the publisher. 2. Any DDL that calls a volatile function, such as NOW() or RAND(), is likely to generate a different value on each replica. It is possible to work around these issues=E2=80=94for example, the publisher can replace = any volatile function calls with a fixed return value when the statement is logged so that the subscribers all get the same value. We will have to consider some other cases. 3. CREATE TABLE AS and SELECT INTO, For example: CREATE TABLE foo AS SELECT field_1, field_2 FROM bar; There are a few issues that can occur here. For one, it=E2=80=99s possi= ble that table bar doesn't exist on the subscriber. Even if =E2=80=9Cbar=E2=80= =9D does exist, it may not be fully up-to-date with the publisher, which would cause a data mismatch on =E2=80=9Cfoo=E2=80=9D between the publisher and su= bscriber. 4. Statements that have nondeterministic side effects (e.g., as caused by triggers, stored procedures, user-defined functions) may result in different side effects occurring on each subscriber. Whether a DDL should be replicated also depends on what granularity do we define DDL replication. For example, we can define DDL replication on these levels: 1. Database level Allows all DDLs for a database to be replicated except for certain edge cases (refer to the edge cases mentioned above). This is likely a major use case, such as in online major version upgrade. 2. Table level Allows DDLs on the published tables to be replicated except for certain edge cases. This is useful for consolidating multiple databases into a single one, e.g. for analytics. 3. Other fine-grained levels base on the object type such as index, function, procedure and view etc. Allows DDLs on certain object types to be replicated. At the moment I=E2=80=99m unsure of a use case for this. To implement such DDL replication levels, we need to modify the CREATE PUBLICATION syntax. For example, to help starting the discussion on the granularity of DDL replication, we can add a new option list =E2=80=98d= dl=E2=80=99 in the WITH definition: CREATE PUBLICATION mypub FOR ALL TABLES with (publish =3D =E2=80=98insert, update, delete, truncate=E2=80=99, ddl =3D = =E2=80=98database=E2=80=99) CREATE PUBLICATION mypub FOR TABLE T1, T2 with (publish =3D =E2=80=98insert, update, delete, truncate=E2=80=99, ddl =3D = =E2=80=98table=E2=80=99) CREATE PUBLICATION mypub FOR TABLE T1, T2 with (publish =3D =E2=80=98insert, update, delete, truncate=E2=80=99, ddl =3D = =E2=80=98table, function, procedure=E2=80=99) We can probably make =E2=80=9Cddl =3D =E2=80=98database=E2=80=99=E2=80=9D v= alid only for the FOR ALL TABLES publication, because it doesn=E2=80=99t really make sense to replica= te all DDLs for a database when only a subset of tables are being replicated (which can cause edge case 1 to occur frequently). =E2=80=9Cddl = =3D =E2=80=98database=E2=80=99=E2=80=9D + FOR ALL TABLES is likely where logica= l replication of DDL is most useful, i.e. for online major versions upgrades. Based on the DDL publication levels we can further implement the logic to conditionally log the DDL commands or to conditionally decode/ship the logical DDL message. Thoughts? Your feedback is appreciated. Thanks, Zheng Li Amazon RDS/Aurora for PostgreSQL