Skip to content

Commit

Permalink
Integrated fixed links.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpe442 committed Jul 2, 2024
1 parent 273852d commit 004b5a9
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ The most common conflict, `INSERT`/`INSERT`, arises where `INSERT` operations on

PGD handles this situation by retaining the most recently inserted tuple of the two according to the originating node's timestamps. (A user-defined conflict handler can override this behavior.)

This conflict generates the `insert_exists` conflict type, which is by default resolved by choosing the newer row, based on commit time, and keeping only that one (`update_if_newer` resolver). You can configure other resolvers. See [Conflict resolution](#conflict-resolution) for details.
This conflict generates the `insert_exists` conflict type, which is by default resolved by choosing the newer row, based on commit time, and keeping only that one (`update_if_newer` resolver). You can configure other resolvers. See [Conflict resolution](04_conflict_resolution) for details.

To resolve this conflict type, you can also use column-level conflict resolution and user-defined conflict triggers.

You can effectively eliminate this type of conflict by using [global sequences](../sequences).
You can effectively eliminate this type of conflict by using [global sequences](../../sequences/#pgd-global-sequences).

### INSERT operations that violate multiple UNIQUE constraints

Expand All @@ -46,7 +46,7 @@ You can also define a different behavior using a conflict trigger.

Where two concurrent `UPDATE` operations on different nodes change the same tuple but not its `PRIMARY KEY`, an `UPDATE`/`UPDATE` conflict can occur on replay.

These can generate different conflict kinds based on the configuration and situation. If the table is configured with [row version conflict detection](#row-version-conflict-detection), then the original (key) row is compared with the local row. If they're different, the `update_differing` conflict is generated. When using [origin conflict detection](#origin-conflict-detection), the origin of the row is checked. (The origin is the node that the current local row came from.) If that changed, the `update_origin_change` conflict is generated. In all other cases, the `UPDATE` is normally applied without generating a conflict.
These can generate different conflict kinds based on the configuration and situation. If the table is configured with [row version conflict detection](03_conflict_detection/#row-version-conflict-detection), then the original (key) row is compared with the local row. If they're different, the `update_differing` conflict is generated. When using [origin conflict detection](03_conflict_detection/#origin-conflict-detection), the origin of the row is checked. (The origin is the node that the current local row came from.) If that changed, the `update_origin_change` conflict is generated. In all other cases, the `UPDATE` is normally applied without generating a conflict.

Both of these conflicts are resolved the same way as `insert_exists`, described in [INSERT/INSERT conflicts](#insertinsert-conflicts).

Expand Down Expand Up @@ -175,12 +175,12 @@ PGD supports deferred unique constraints. If a transaction can commit on the sou

One node can update a row that another node deletes at ths same time. In this case an `UPDATE`/`DELETE` conflict can occur on replay.

If the deleted row is still detectable (the deleted row wasn't removed by `VACUUM`), the `update_recently_deleted` conflict is generated. By default, the `UPDATE` is skipped, but you can configure the resolution for this. See [Conflict resolution](#conflict-resolution) for details.
If the deleted row is still detectable (the deleted row wasn't removed by `VACUUM`), the `update_recently_deleted` conflict is generated. By default, the `UPDATE` is skipped, but you can configure the resolution for this. See [Conflict resolution](04_conflict_resolution) for details.

The database can clean up the deleted row by the time the `UPDATE` is received in case the local node is lagging behind in replication. In this case, PGD can't differentiate between `UPDATE`/`DELETE` conflicts and [INSERT/UPDATE conflicts](#insertupdate-conflicts). It generates the `update_missing` conflict.

Another type of conflicting `DELETE` and `UPDATE` is a `DELETE` that comes after the row was updated locally. In this situation, the outcome depends on the type of conflict detection used. When using the
default, [origin conflict detection](#origin-conflict-detection), no conflict is detected, leading to the `DELETE` being applied and the row removed. If you enable [row version conflict detection](#row-version-conflict-detection), a `delete_recently_updated` conflict is generated. The default resolution for a `delete_recently_updated` conflict is to `skip` the deletion. However, you can configure the resolution or a conflict trigger can be configured to handle it.
default, [origin conflict detection](03_conflict_detection/#origin-conflict-detection), no conflict is detected, leading to the `DELETE` being applied and the row removed. If you enable [row version conflict detection](03_conflict_detection/#row-version-conflict-detection), a `delete_recently_updated` conflict is generated. The default resolution for a `delete_recently_updated` conflict is to `skip` the deletion. However, you can configure the resolution or a conflict trigger can be configured to handle it.

### INSERT/UPDATE conflicts

Expand Down Expand Up @@ -231,7 +231,7 @@ Using `insert_or_error` (or in some cases the `insert_or_skip` conflict resolver

If these are problems, we recommend tuning freezing settings for a table or database so that they're correctly detected as `update_recently_deleted`.

Another alternative is to use [Eager Replication](eager) to prevent these conflicts.
Another alternative is to use [Eager Replication](../eager) to prevent these conflicts.

`INSERT`/`DELETE` conflicts can also occur with three or more nodes. Such a conflict is identical to `INSERT`/`UPDATE` except with the `UPDATE` replaced by a `DELETE`. This can result in a `delete_missing`
conflict.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This avoidance happens naturally in many applications. For example, many consume

You might make a change just before a node goes down, so the change seems to be lost. You might then make the same change again, leading to two updates on different nodes. When the down node comes back up, it tries to send the older change to other nodes. It's rejected because the last update of the data is kept.

For `INSERT`/`INSERT` conflicts, use [global sequences](../sequences) to prevent this type of conflict.
For `INSERT`/`INSERT` conflicts, use [global sequences](../../sequences//#pgd-global-sequences) to prevent this type of conflict.

For applications that assign relationships between objects, such as a room-booking application, applying `update_if_newer` might not give an acceptable business outcome. That is, it isn't useful to confirm to two people separately that they have booked the same room. The simplest resolution is to use Eager Replication to ensure that only one booking succeeds. More complex ways might be possible depending on the application. For example, you can assign 100 seats to each node and allow those to be booked by a writer on that node. But if none are available locally, use a distributed locking scheme or Eager Replication after most seats are reserved.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ PGD provides these mechanisms for conflict detection:

- [Origin conflict detection](#origin-conflict-detection) (default)
- [Row version conflict detection](#row-version-conflict-detection)
- [Column-level conflict detection](column-level-conflicts)
- [Column-level conflict detection](../column-level-conflicts)

## Origin conflict detection

Expand All @@ -23,7 +23,7 @@ Origin info is available only up to the point where a row is frozen. Updates arr
A node that was offline that reconnects and begins sending data changes can cause divergent
errors if the newly arrived updates are older than the frozen rows that they update. Inserts and deletes aren't affected by this situation.

We suggest that you don't leave down nodes for extended outages, as discussed in [Node restart and down node recovery](../node_management).
We suggest that you don't leave down nodes for extended outages, as discussed in [Node restart and down node recovery](../../node_management/node_recovery/).

On EDB Postgres Extended Server and EDB Postgres Advanced Server, PGD holds back the freezing of rows while a node is down. This mechanism handles this situation gracefully so you don't need to change parameter settings.

Expand All @@ -37,7 +37,7 @@ Freezing normally occurs when a row being vacuumed is older than `vacuum_freeze_

Choose values based on the transaction rate, giving a grace period of downtime before removing any conflict data from the database node. For example, when `vacuum_freeze_min_age` is set to 500 million, a node performing 1000 TPS can be down for just over 5.5 days before conflict data is removed. The CommitTS data structure takes on-disk space of 5 GB with that setting, so lower transaction rate systems can benefit from lower settings.

Initially recommended settings are:
Initially, recommended settings are:

```sql
# 1 billion = 10GB
Expand Down Expand Up @@ -72,9 +72,9 @@ Although the counter is incremented only on `UPDATE`, this technique allows conf
This approach resembles Lamport timestamps and fully prevents the ABA problem for conflict detection.

!!! Note
The row-level conflict resolution is still handled based on the [conflict resolution](#conflict-resolution) configuration even with row versioning. The way the row version is generated is useful only for detecting conflicts. Don't rely on it as authoritative information about which
The row-level conflict resolution is still handled based on the [conflict resolution](04_conflict_resolution) configuration even with row versioning. The way the row version is generated is useful only for detecting conflicts. Don't rely on it as authoritative information about which
version of row is newer.

To determine the current conflict resolution strategy used for a specific table, refer to the column `conflict_detection` of the view `bdr.tables`.
To determine the current conflict detection strategy used for a specific table, refer to the column `conflict_detection` of the view `bdr.tables`.

To change the current conflict detection strategy, use [bdr.alter_table_conflict_detection](../../reference/conflicts/#bdralter_table_conflict_detection).
4 changes: 2 additions & 2 deletions product_docs/docs/pgd/5/consistency/conflicts/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ PGD to provide the application a range of choices for how to resolve conflicts.

By default, conflicts are resolved at the row level. When changes from two nodes conflict, PGD picks either the local or remote tuple and the discards the other. For example, the commit timestamps might be compared for the two conflicting changes and the newer one kept. This approach ensures that all nodes converge to the same result and establishes commit-order-like semantics on the whole cluster.

Conflict handling is configurable, as described in [Conflict resolution](#conflict-resolution). PGD can detect conflicts and handle them differently for each table using conflict triggers, described in [Stream triggers](../striggers).
Conflict handling is configurable, as described in [Conflict resolution](04_conflict_resolution). PGD can detect conflicts and handle them differently for each table using conflict triggers, described in [Stream triggers](../../striggers).

Column-level conflict detection and resolution is available with PGD, described in [CLCD](column-level-conflicts).
Column-level conflict detection and resolution is available with PGD, described in [CLCD](../column-level-conflicts).

By default, all conflicts are logged to `bdr.conflict_history`. If conflicts are possible, then table owners must monitor for them and analyze how to avoid them or make plans to handle them regularly as an application task. The [LiveCompare](/livecompare/latest) tool is also available to scan regularly for divergence.

Expand Down

0 comments on commit 004b5a9

Please sign in to comment.