Commit scopes give applications granular control about durability and consistency of EDB Postgres Distributed.
A commit scope is a set of rules that describes the behavior of the system as transactions are committed. The actual behavior depends on which a kind of commit scope a commit scope's rule uses Synchronous Commit, Group Commit, Commit At Most Once, Lag Control, or combination of these.
While most commit scope kinds control the processing of the transaction, Lag Control is the exception as it dynamically regulates the performance of the system in response to replication operations being slow or queued up. It is typically used, though, in combination with other commit scope kinds
Commit scope structure
Every commit scope has a name (a commit_scope_name).
Each commit scope has one or more rules.
Each rule within the commit scope has an origin_node_group which together uniquely identify the commit scope rule.
The origin_node_group is a PGD group and it defines the nodes which will apply this rule when they are the originators of a transaction.
Finally there is the rule which defines what kind of commit scope or combination of commit scope kinds should be applied to those transactions.
So if a commit scope has a rule that reads:
origin_node_group := 'example_bdr_group', rule := 'MAJORITY (example_bdr_group) GROUP COMMIT',
Then, the rule is applied when any node in the example_bdr_group issues a transaction.
The rule itself specifies how many nodes of a specified group will need to confirm the change - MAJORITY (example_bdr_group) - followed by the commit scope kind itself - GROUP COMMIT. This translates to requiring that any two nodes in example_bdr_group must confirm the change before the change can be considered as comitted.
How a commit scope is selected
When any change takes place, PGD looks up which commit scope is should be used for the transaction or node.
If a transaction specifies a commit scope, that scope will be used.
If not specified, the system will search for a default commit scope. Default commit scopes are a group level setting. The system consults the group tree. Starting at the bottom of the group tree with the node's group and working up, it searches for any group which has a default_commit_scope setting defined. This commit scope will then be used.
If no default_commit_scope is found then the node's GUC, bdr.commit_scope is used. And if that isn't set or is set to local then no commit scope applies and PGD's async replication is used.
A rule's origin_node_group is matched differently depending on how the commit scope is activated:
- As a default commit scope set via a group's
default_commit_scope, PGD ascends the group tree from the node's group, so a rule defined on a parent or top-level group applies to subgroup nodes. - Activated explicitly via
SET [LOCAL] bdr.commit_scope, the rule is matched only against the node's own group. If no rule has that exact group as itsorigin_node_group, no commit scope applies and the transaction silently falls back to async replication.
Warning
Setting bdr.commit_scope to a scope whose rules are all defined on a parent group does not raise an error, but the scope is not applied and the commit uses async replication. To use such a scope with SET LOCAL bdr.commit_scope on a subgroup node, create the rule with that subgroup as origin_node_group.
Creating a Commit Scope
Use bdr.create_commit_scope to add our example rule to a commit scope. For example:
SELECT bdr.create_commit_scope( commit_scope_name := 'example_scope', origin_node_group := 'example_bdr_group', rule := 'MAJORITY (example_bdr_group) GROUP COMMIT', wait_for_ready := true );
This will add the rule MAJORITY (example_bdr_group) GROUP COMMIT for any transaction originating from the example_bdr_group to a scope called example_scope.
If no rules previously existed in example_scope, then adding this rule would make the scope exist.
When a rule is added, the origin_node_group must already exist. If it does not, the whole add operation will be discarded with an error.
The rule will then be evaluated. If the rule mentions groups that don't exist or the settings on the group are incompatible with other configuration setting on the group's nodes, a warning will be emitted, but the rule will be added.
Once the rule is added, the commit scope will be available for use.
The wait_for_ready controls whether the bdr.create_commit_scope() call blocks until the rule has been added to the relevant nodes. The setting defaults to true and can be omitted.
Using a commit scope
To use our example scope, we can set bdr.commit_scope within a transaction
BEGIN; SET LOCAL bdr.commit_scope = 'example_scope'; ... COMMIT;
You must set the commit scope before the transaction writes any data.
You can set a commit scope as a default for a group or subgroup using bdr.alter_node_group_option:
SELECT bdr.alter_node_group_option( node_group_name := 'example_bdr_group', config_key := 'default_commit_scope', config_value := 'example_scope' );
To completely clear the default for a group or subgroup, set the default_commit_scope value to local:
SELECT bdr.alter_node_group_option( node_group_name := 'example_bdr_group', config_key := 'default_commit_scope', config_value := 'local' );
You can also make this change using PGD CLI:
pgd set-group-options example-bdr-group --option default_commit_scope=example_scope
And you can clear the default using PGD CLI by setting the value to local:
pgd set-group-options example-bdr-group --option default_commit_scope=local
Finally, you can set the default commit_scope for a node using:
SET bdr.commit_scope = 'example_scope';
Set bdr.commit_scope to local to use the PGD default async replication.