Skip to content

DOCS-1341-PGD-5.8-branch #6665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
aac1843
Started 5.8 branch for PGD.
jpe442 Mar 31, 2025
eca8915
changed version in index
jpe442 Mar 31, 2025
430011a
update generated release notes
github-actions[bot] Mar 31, 2025
1009a0e
Updated rel notes to add 5.8
djw-m Apr 28, 2025
307e76e
Porting galloc content to 5.8
djw-m May 6, 2025
c2bc12f
Changes with expanded language
djw-m Apr 30, 2025
70510b7
Fix up according to notes, update versions command for 5.7
djw-m May 7, 2025
1065ec2
Add pgd_bench usability enhancement to relnotes.
ibarwick May 13, 2025
6effee5
update generated release notes
github-actions[bot] May 13, 2025
9deae91
DOCS-1256 PGD 5.8 Draft release notes redux (#6769)
djw-m May 14, 2025
75229f9
PGD 5.8: update release notes
ibarwick May 19, 2025
eb828d4
update generated release notes
github-actions[bot] May 19, 2025
f91f49b
Fix cli entries
djw-m May 19, 2025
d9d4f07
update generated release notes
github-actions[bot] May 19, 2025
b256f43
Tidy up on release notes
djw-m May 21, 2025
3f84977
update generated release notes
github-actions[bot] May 21, 2025
44a12c8
Added the DDL SO node fixes
djw-m May 21, 2025
506fbb3
update generated release notes
github-actions[bot] May 21, 2025
ce24507
Locate DDL SO text correctly
djw-m May 21, 2025
77567d0
Add temporary highlights
djw-m May 21, 2025
0c325e6
update generated release notes
github-actions[bot] May 21, 2025
dce99fb
cdc-failover late update
djw-m May 21, 2025
6698f8f
Final release note updates
djw-m May 22, 2025
ad2132e
update generated release notes
github-actions[bot] May 22, 2025
52499fc
Updated release notes
djw-m May 22, 2025
21cffb3
restore PGD 5.7 docs
djw-m May 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions product_docs/docs/pgd/5.8/appusage/behavior.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
title: Application behavior
navTitle: Application behavior
---

Much of PGD's replication behavior is transparent to applications. Understanding how it
achieves that and the elements that aren't transparent is important to successfully developing
an application that works well with PGD.

### Replication behavior

PGD supports replicating changes made on one node to other nodes.

PGD, by default, replicates all changes from INSERT, UPDATE, DELETE, and TRUNCATE
operations from the source node to other nodes. Only the final changes are sent,
after all triggers and rules are processed. For example, `INSERT ... ON CONFLICT
UPDATE` sends either an insert or an update, depending on what occurred on the
origin. If an update or delete affects zero rows, then no changes are sent.

You can replicate INSERT without any preconditions.

For updates and deletes to replicate on other nodes, PGD must be able to
identify the unique rows affected. PGD requires that a table have either a
PRIMARY KEY defined, a UNIQUE constraint, or an explicit REPLICA IDENTITY
defined on specific columns. If one of those isn't defined, a warning is
generated, and later updates or deletes are explicitly blocked. If REPLICA
IDENTITY FULL is defined for a table, then a unique index isn't required. In
that case, updates and deletes are allowed and use the first non-unique index
that's live, valid, not deferred, and doesn't have expressions or WHERE clauses.
Otherwise, a sequential scan is used.

### Truncate

You can use TRUNCATE even without a defined replication identity. Replication of
TRUNCATE commands is supported, but take care when truncating groups of tables
connected by foreign keys. When replicating a truncate action, the subscriber
truncates the same group of tables that was truncated on the origin, either
explicitly specified or implicitly collected by CASCADE, except in cases where
replication sets are defined. See [Replication sets](../repsets) for
details and examples. This works correctly if all affected tables are part of
the same subscription. But if some tables to truncate on the subscriber have
foreign-key links to tables that aren't part of the same (or any) replication
set, then applying the truncate action on the subscriber fails.

### Row-level locks

Row-level locks taken implicitly by INSERT, UPDATE, and DELETE commands are
replicated as the changes are made. Table-level locks taken implicitly by
INSERT, UPDATE, DELETE, and TRUNCATE commands are also replicated. Explicit
row-level locking (`SELECT ... FOR UPDATE/FOR SHARE`) by user sessions isn't
replicated, nor are advisory locks. Information stored by transactions running
in SERIALIZABLE mode isn't replicated to other nodes. The transaction isolation
level of SERIALIAZABLE is supported, but transactions aren't serialized across
nodes in the presence of concurrent transactions on multiple nodes.

If DML is executed on multiple nodes concurrently, then potential conflicts
might occur if executing with asynchronous replication. You must either handle
these or avoid them. Various avoidance mechanisms are possible, discussed in
[Conflicts](../conflict-management/conflicts).

### Sequences

Sequences need special handling, described in [Sequences](../sequences). This is
because in a cluster, sequences must be global to avoid nodes creating
conflicting values. Global sequences are available with global locking to ensure
integrity.

### Binary objects

Binary data in BYTEA columns is replicated normally, allowing "blobs" of data up
to 1 GB. Use of the PostgreSQL "large object" facility isn't supported in PGD.

### Rules

Rules execute only on the origin node so aren't executed during apply,
even if they're enabled for replicas.

### Base tables only

Replication is possible only from base tables to base tables. That is, the
tables on the source and target on the subscription side must be tables, not
views, materialized views, or foreign tables. Attempts to replicate tables other
than base tables result in an error. DML changes that are made through updatable
views are resolved to base tables on the origin and then applied to the same
base table name on the target.

### Partitioned tables

PGD supports partitioned tables transparently, meaning that you can add a
partitioned table to a replication set and changes that involve any of the
partitions are replicated downstream.

### Triggers

By default, triggers execute only on the origin node. For example, an INSERT
trigger executes on the origin node and is ignored when you apply the change on
the target node. You can specify for triggers to execute on both the origin node
at execution time and on the target when it's replicated (*apply time*) by using
`ALTER TABLE ... ENABLE ALWAYS TRIGGER`. Or, use the `REPLICA` option to execute
only at apply time: `ALTER TABLE ... ENABLE REPLICA TRIGGER`.

Some types of trigger aren't executed on apply, even if they exist on a
table and are currently enabled. Trigger types not executed are:

- Statement-level triggers (`FOR EACH STATEMENT`)
- Per-column UPDATE triggers (`UPDATE OF column_name [, ...]`)

PGD replication apply uses the system-level default search_path. Replica
triggers, stream triggers, and index expression functions can assume other
search_path settings that then fail when they execute on apply. To prevent this
from occurring, use any of these techniques:

- Resolve object references clearly using only the default search_path.
- Always use fully qualified references to objects, for example, `schema.objectname`.
- Set the search path for a function using `ALTER FUNCTION ... SET search_path
= ...` for the functions affected.

PGD assumes that there are no issues related to text or other collatable
datatypes, that is, all collations in use are available on all nodes, and the
default collation is the same on all nodes. Replicating changes uses equality
searches to locate Replica Identity values, so this does't have any effect
except where unique indexes are explicitly defined with nonmatching collation
qualifiers. Row filters might be affected by differences in collations if
collatable expressions were used.

### Toast

PGD handling of very long "toasted" data in PostgreSQL is transparent to the
user. The TOAST "chunkid" values likely differ between the same row on different
nodes, but that doesn't cause any problems.

### Other restrictions

PGD can't work correctly if Replica Identity columns are marked as external.

PostgreSQL allows CHECK() constraints that contain volatile functions. Since PGD
reexecutes CHECK() constraints on apply, any subsequent reexecution that
doesn't return the same result as before causes data divergence.

PGD doesn't restrict the use of foreign keys. Cascading FKs are allowed.
59 changes: 59 additions & 0 deletions product_docs/docs/pgd/5.8/appusage/dml-ddl.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: DML and DDL replication and nonreplication
navTitle: DML and DDL replication
---

The two major classes of SQL statement are DML and DDL.

* DML is the data modification language and is concerned with the SQL statements that modify the data stored in tables. It includes UPDATE, DELETE, and INSERT.

* DDL is the data definition language and is concerned with the SQL statements that modify how the data is stored. It includes CREATE, ALTER, and DROP.

PGD handles each class differently.

## DML replication

PGD doesn't replicate the DML statement. It replicates the changes caused by the
DML statement. For example, an UPDATE that changed two rows replicates two
changes, whereas a DELETE that didn't remove any rows doesn't replicate
anything. This means that the results of executing volatile statements are
replicated, ensuring there's no divergence between nodes as might occur with
statement-based replication.

## DDL replication

DDL replication works differently from DML. For DDL, PGD replicates the statement,
which then executes on all nodes. So a `DROP TABLE IF EXISTS` might not
replicate anything on the local node, but the statement is still sent to other
nodes for execution if DDL replication is enabled. For details, see
[DDL replication](../ddl).

PGD works to ensure that intermixed DML and DDL statements work correctly, even
in the same transaction.

## Nonreplicated statements

Outside of those two classes are SQL commands that PGD, by design, doesn't
replicate. None of the following user commands are replicated by PGD, so their
effects occur on the local/origin node only:

- Cursor operations (DECLARE, CLOSE, FETCH)
- Execution commands (DO, CALL, PREPARE, EXECUTE, EXPLAIN)
- Session management (DEALLOCATE, DISCARD, LOAD)
- Parameter commands (SET, SHOW)
- Constraint manipulation (SET CONSTRAINTS)
- Locking commands (LOCK)
- Table maintenance commands (VACUUM, ANALYZE, CLUSTER, REINDEX)
- Async operations (NOTIFY, LISTEN, UNLISTEN)

Since the `NOTIFY` SQL command and the `pg_notify()` functions aren't
replicated, notifications aren't reliable in case of failover. This means that
notifications can easily be lost at failover if a transaction is committed just
when the server crashes. Applications running `LISTEN` might miss notifications
in case of failover.

This is true in standard PostgreSQL replication, and PGD doesn't yet improve on
this.

CAMO and Eager Replication options don't allow the `NOTIFY` SQL command or the
`pg_notify()` function.
76 changes: 76 additions & 0 deletions product_docs/docs/pgd/5.8/appusage/extensions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: Using extensions with PGD
navTitle: Extension usage
deepToC: true
---

## PGD and other PostgreSQL extensions

PGD is implemented as a PostgreSQL extension (see [Supported Postgres database servers](../overview/architecture-and-performance/#supported-postgres-database-servers)). It takes advantage of PostgreSQL's expandability and flexibility to modify low-level system behavior to provide multi-master replication.

In principle, extensions provided by community PostgreSQL, EDB Postgres Advanced Server, and third-party extensions can be used with PGD. However, the distributed nature of PGD means that you need to carefully consider and plan the extensions you select and install.

### Extensions providing logical decoding

Extensions providing logical decoding, such as [wal2json](https://github.com/eulerto/wal2json), may in theory work with PGD. However, there's no support for failover, meaning any WAL stream being read from such an extension can be interrupted.

### Extensions providing replication or HA functionality

Any extension extending PostgreSQL with functionality related to replication or HA/failover is unlikely to work well with PGD and may even be detrimental to the health of the PGD cluster. We recommend avoiding these.

## Supported extensions

These extensions are explicitly supported by PGD.

### EDB Advanced Storage table access methods

The [EDB Advanced Storage Pack](/pg_extensions/advanced_storage_pack/) provides a selection of table access methods (TAMs) implemented as extensions. The following TAMs are certified for use with PGD:

- [Autocluster](/pg_extensions/advanced_storage_pack/#autocluster)
- [Refdata](/pg_extensions/advanced_storage_pack/#refdata)

For more details, see [Table access methods](table-access-methods).

### pgaudit

PGD was modified to ensure compatibility with the [pgaudit](https://www.pgaudit.org/) extension.
See [Postgres settings](../postgres-configuration/#postgres-settings) for configuration information.


## Installing extensions

PostgreSQL extensions provide SQL objects, such as functions, datatypes, and, optionally, one or more shared libraries. These must be loaded into the PostgreSQL backend before you can install and use the extension.

!!! Warning

The relevant extension packages must be available on all nodes in the cluster. Otherwise extension installation can fail and impact cluster stability.

If PGD is deployed using [Trusted Postgres Architect](/tpa/latest/), configure extensions using that tool.
For details, see [Adding Postgres extensions](/tpa/latest/reference/postgres_extension_configuration).

The following is relevant for manually configured PGD installations.

### Configuring shared_preload_libraries

If an extension provides a shared library, include this library in the [`shared_preload_libraries`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES) configuration parameter before installing the extension.

`shared_preload_libraries` consists of a comma-separated list of extension names.
It must include `bdr`.
The order in which you specify other extensions generally doesn't matter. However if you're using the pgaudit extension, `pgaudit` must appear in the list before `bdr`.

Configure `shared_preload_libraries` on all nodes in the cluster before installing the extension with `CREATE EXTENSION`.
You must restart PostgreSQL to activate the new configuration.

See also [Postgres settings](../postgres-configuration/#postgres-settings).


### Installing the extension

Install the extension using the `CREATE EXTENSION` command.
You need to do this on only one node in the cluster. PGD's DDL replication will ensure that it propagates to all other nodes.

!!! Warning

Do not attempt to install extensions manually on each node by, for example, disabling DDL replication before executing `CREATE EXTENSION`.

Do not use a command such as `bdr.replicate_ddl_command()` to execute `CREATE EXTENSION`.
114 changes: 114 additions & 0 deletions product_docs/docs/pgd/5.8/appusage/feature-compatibility.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: Feature compatibility
navTitle: Feature compatibility
---

## Server feature/commit scope interoperability

Not all server features work with all commit scopes. This table shows the ones that interoperate.

<table style="table-layout: fixed">
<thead>
<tr>
<td style="text-align:center; width:33%"></td>
<td style="text-align:center"> Async<br/><div style="font-size:smaller">(default)</div></td>
<td style="text-align:center"><a href="../parallelapply">Parallel<br/>Apply</a> </td>
<td style="text-align:center"><a href="../transaction-streaming">Transaction<br/>Streaming</a> </td>
<td style="text-align:center"><a href="../decoding_worker">Single<br/>Decoding<br/>Worker</a> </td>
</tr>
</thead>
<tbody>
<tr>
<td> <a href="../commit-scopes/group-commit">Group Commit</a> </td>
<td style="text-align:center"> ⛔︎ </td>
<td style="text-align:center"> ❌ </td>
<td style="text-align:center"> ❌<sup>❗️</sup> </td>
<td style="text-align:center"> ✅ </td>
</tr>
<tr>
<td> <a href="../commit-scopes/camo">CAMO</a> </td>
<td style="text-align:center"> ⛔︎ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ❌ </td>
<td style="text-align:center"> ❌ </td>
</tr>
<tr>
<td> <a href="../commit-scopes/lag-control">Lag Control</a> </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
</tr>
<tr>
<td> <a href="../commit-scopes/synchronous_commit">Synchronous Commit</a> </td>
<td style="text-align:center"> ⛔︎ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
</tr>
</tbody>
</table>

**Legend**:&nbsp;&nbsp;&nbsp; ⛔︎ Not applicable&nbsp;&nbsp;&nbsp; ❌ Does not interoperate&nbsp;&nbsp;&nbsp; ✅ Interoperates


#### Notes

⛔︎&nbsp;:&nbsp;The Async column in the table represents PGD without a synchronous commit scope in use. Lag Control isn't a synchronous commit scope. It's a controlling commit scope and is therefore available with asynchronous operations.

<sup>❗️</sup>&nbsp;:&nbsp;Attempting to use Group Commit and Transaction Streaming presents a warning. The warning suggests that you disable transaction streaming, and the transaction appears to take place. In the background, Group Commit was disabled to allow the transaction to occur.



## Commit scope/commit scope interoperability

Although you can't mix commit scopes, you can [combine rules](../commit-scopes/commit-scope-rules/#combining-rules) with an `AND` operator. This table shows where commit scopes can be combined.

<table style="table-layout: fixed">
<thead>
<tr>
<td style="text-align:center; width:33%"></td>
<td style="text-align:center"> <a href="../commit-scopes/group-commit">Group<br/>Commit</a></td>
<td style="text-align:center"><a href="../commit-scopes/camo">CAMO</a> </td>
<td style="text-align:center"><a href="../commit-scopes/lag-control">Lag<br/>Control</a> </td>
<td style="text-align:center"><a href="../commit-scopes/synchronous_commit">Synchronous<br/>Commit</a> </td>
</tr>
</thead>
<tbody>
<tr>
<td> <a href="../commit-scopes/group-commit">Group Commit</a> </td>
<td style="text-align:center"> ⛔︎ </td>
<td style="text-align:center"> ❌ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
</tr>
<tr>
<td> <a href="../commit-scopes/camo">CAMO</a> </td>
<td style="text-align:center"> ❌ </td>
<td style="text-align:center"> ⛔︎ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ❌ </td>
</tr>
<tr>
<td> <a href="../commit-scopes/lag-control">Lag Control</a> </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ⛔︎ </td>
<td style="text-align:center"> ✅ </td>
</tr>
<tr>
<td> <a href="../commit-scopes/synchronous_commit">Synchronous Commit</a> </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ❌ </td>
<td style="text-align:center"> ✅ </td>
<td style="text-align:center"> ⛔︎ </td>
</tr>
</tbody>
</table>

**Legend**:&nbsp;&nbsp;&nbsp; ⛔︎ Not applicable&nbsp;&nbsp;&nbsp; ❌ Does not combine&nbsp;&nbsp;&nbsp; ✅ Combines

#### Notes

Each commit scope implicitly works with itself.

Loading
Loading