You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/configuration/pgdog.toml/rewrite.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,7 @@ The `rewrite` section controls PgDog's automatic SQL rewrites for sharded databa
31
31
|`primary_key`| Behavior when an `INSERT` is missing a `BIGINT` primary key: `error` rejects the statement,<br>`rewrite` auto-injects `pgdog.unique_id()` for missing keys,<br>`ignore` allows the INSERT without modification. |`"ignore"`|
32
32
33
33
!!! note "Two-phase commit"
34
-
Consider enabling [two-phase commit](../../features/sharding/2pc.md) when either feature is set to `rewrite`. Without it, rewrites are committed shard-by-shard and can leave partial changes if a transaction fails.
34
+
Consider enabling [two-phase commit](../../features/sharding/2pc/index.md) when either feature is set to `rewrite`. Without it, rewrites are committed shard-by-shard and can leave partial changes if a transaction fails.
This feature is new and experimental. Please make sure to test it before
5
9
deploying to production and let us know if you run into any issues.
6
10
7
-
[Two-phase commit](index.md) requires different state to be stored on each shard during the commit phase. If PgDog were to crash during this step, the state in which each transaction is on each shard would be impossible to determine.
11
+
[Two-phase commit](index.md) requires different state to be stored on each shard during the commit phase. If PgDog were to crash during this step, it would be impossible to determine the state of each transaction on each shard.
8
12
9
-
To avoid this, PgDog can write the commit state of each transaction into its own write-ahead log (WAL). When its restarted, PgDog reads from the log and restores the 2pc state to what it was, allowing it to finish any in-flight transactions.
13
+
To avoid this, PgDog can write the commit state of each two-phase transaction into its own write-ahead log (WAL). When it's restarted, PgDog reads from the log and restores the 2PC state to what it was, allowing it to finish any in-flight transactions.
10
14
11
15
## How it works
12
16
13
-
The WAL requires PgDog to run on a machine with a durable storage medium. If you're using our [Helm chart](../../installation.md#kubernetes), you can enable this with configuration:
17
+
The WAL requires PgDog to run on a machine with a durable storage medium. If you're using our [Helm chart](../../../installation.md#kubernetes), you can enable this directly in the chart:
14
18
15
19
```yaml title="values.yaml"
16
20
statefulSet:
@@ -19,7 +23,7 @@ statefulSet:
19
23
enabled: true
20
24
```
21
25
22
-
The `walPvc` flag will provision a Persistent Volume Claim (PVC) and attach the volume to each replica in the deployment. It will also configure the necessary [`pgdog.toml`](../../configuration/pgdog.toml/general.md) settings:
26
+
The `walPvc` flag will provision a Persistent Volume Claim (PVC) and attach its own volume to each replica in the deployment. It will also configure the necessary [`pgdog.toml`](../../../configuration/pgdog.toml/general.md) settings:
23
27
24
28
=== "pgdog.toml"
25
29
```toml
@@ -28,42 +32,42 @@ The `walPvc` flag will provision a Persistent Volume Claim (PVC) and attach the
28
32
```
29
33
=== "Helm chart"
30
34
```yaml
31
-
# These are configured automatically.
35
+
# This is configured automatically.
32
36
twoPhaseCommitWalDir: "/var/lib/pgdog/wal"
33
37
```
34
38
35
39
Our WAL has no Kubernetes dependency, so you can use it if you're deploying PgDog anywhere else, as long as you have a durable disk, e.g., EBS volume, SSD, etc.
36
40
37
41
### Configuration
38
42
39
-
The WAL has a couple settings that allows you to tweak its performance:
43
+
The WAL has a couple of settings that allow you to tweak its performance:
40
44
41
45
| Setting | Description |
42
46
|-|-|
43
-
| `two_phase_commit_fsync_interval` | Wait this long (in ms, **0** by default) before calling `fsync` on a group of WAL records written to the log. |
44
-
| `two_phase_commit_checkpoint_interval` | How often the checkpointer runs (in ms, **15 seconds** by default) to remove unnecessary WAL segments. |
47
+
| `two_phase_commit_wal_fsync_interval` | Wait this long (in ms, **0** by default) before calling `fsync` on a group of WAL records written to the log. |
48
+
| `two_phase_commit_wal_checkpoint_interval` | How often the checkpointer runs (in ms, **15 seconds** by default) to remove unnecessary WAL segments. |
45
49
| `two_phase_commit_wal_segment_size` | The size of each WAL segment, in bytes. The default, **16MB**, is usually good enough. |
46
50
47
-
The default settings there are usually optimal for most deployments. The fsync interval lever allows you to optimize WAL disk performance in highly concurrenct scenarios, e.g., thousands of clients
48
-
executing 2pc transactions concurrently.
51
+
The default settings are usually optimal for most deployments. The fsync interval allows you to optimize WAL disk performance in highly concurrent scenarios, e.g., thousands of clients
52
+
executing 2PC transactions concurrently.
49
53
50
54
## Architecture
51
55
52
-
PgDog's write-ahead log architecture is loosly based on Postgres, with some minor differences. Like Postgres, PgDog implements it using three independent components:
56
+
PgDog's write-ahead log architecture is loosely based on Postgres, with some differences. Like Postgres, PgDog implements it using three independent components:
53
57
54
58
| Component | Description |
55
59
|-|-|
56
-
| [WAL writer](#wal-writer) | Background thread responsible for writing records to WAL segments (files). |
57
-
| [Checkpointer](#checkpointer) | Background thread responsible for removing old WAL segments no longer necessary for recovery. |
58
-
| [Recovery](#recovery) | Foreground thread that runs on PgDog startup and replays the WAL to restore its in-memory state to a consistent point. |
60
+
| [WAL writer](#wal-writer) | Background task responsible for writing records to WAL segments (files). |
61
+
| [Checkpointer](#checkpointer) | Background task responsible for removing old WAL segments no longer necessary for recovery. |
62
+
| [Recovery](#recovery) | Foreground task that runs on PgDog startup and replays the WAL to restore its in-memory state to a consistent point. |
59
63
60
64
### WAL writer
61
65
62
66
The WAL writer is a background task (we are using Tokio under the hood), which is responsible for writing data into the write-ahead log. It receives records from clients via a synchronization primitive (a queue) and writes them to disk, in batches.
63
67
64
68
Once written, the WAL writer sends a signal back to each client notifying them that their transaction state is safe on disk, and they can proceed. The clients then execute the transaction control statements against the Postgres shards themselves (e.g., `PREPARE TRANSACTION`, `COMMIT PREPARED`).
65
69
66
-
If PgDog were to crash at any time, the state of each transaction can be restored from disk and the transaction control statements replayed against the Postgres shards, either rolling back or comitting a two-phase transaction.
70
+
If PgDog were to crash at any time, the state of each transaction can be restored from disk and the transaction control statements replayed against the Postgres shards, either rolling back or committing a two-phase transaction.
67
71
68
72
#### WAL segments
69
73
@@ -83,30 +87,30 @@ By default, PgDog's segment size is **16MB**, just like Postgres. This ensures t
83
87
84
88
##### Segment size
85
89
86
-
The segments are rotated by a background task asynchronously. This is one key difference between PgDog's implementation and Postgres: the segment size isn't guaranteed. While the rotation takes place, in-flight transactions state is written to the previous segment. This removes the need for us to _lock_ the WAL during a write, i.e., implementing our own version of `WALWriteLock`.
90
+
The segments are rotated asynchronously by a background task. This is one key difference between PgDog's implementation and Postgres: the segment size isn't guaranteed. While the rotation takes place, in-flight transaction state is written to the previous segment. This removes the need for us to _lock_ the WAL during a write, i.e., implementing our own version of `WALWriteLock`.
87
91
88
92
#### Partial records
89
93
90
94
All of our WAL segments contain complete records. This makes [recovery](#recovery) easier, but also contributes to the variable [segment size](#segment-size).
91
95
92
96
### Checkpointer
93
97
94
-
The checkpointer is a background task that runs on a loop and removes any WAL segments that are no longer needed for [recovery](#recovery). These segments contain 2pc stages for transactions that have been already been fully committed to Postgres.
98
+
The checkpointer is a background task that runs in a loop and removes any WAL segments that are no longer needed for [recovery](#recovery). These segments contain 2PC stages for transactions that have already been fully committed to Postgres.
95
99
96
-
Unlike the Postgres checkpointer which needs to update data files to do its job, PgDog's checkpointer only needs to delete unused WAL segments. This makes it very fast. It runs on a regular interval, configurable in [`pgdog.toml`](../../configuration/pgdog.toml/general.md):
100
+
Unlike the Postgres checkpointer which needs to update data files to do its job, PgDog's checkpointer only needs to delete unused WAL segments. This makes it very fast. It runs on a regular interval, configurable in [`pgdog.toml`](../../../configuration/pgdog.toml/general.md):
97
101
98
102
=== "pgdog.toml"
99
103
```toml
100
104
[general]
101
-
two_phase_commit_checkpoint_interval = 15_000
105
+
two_phase_commit_wal_checkpoint_interval = 15_000
102
106
```
103
107
=== "Helm chart"
104
108
```yaml
105
-
twoPhaseCommitCheckpointInterval: 15_000
109
+
twoPhaseCommitWalCheckpointInterval: 15_000
106
110
```
107
111
108
112
### Recovery
109
113
110
-
The recovery process's job is to read all available WAL segments and replay their data into the in-memory state of the [2pc](index.md#error-handling) transaction manager. Once the replay is complete, the manager state should be restored to what it was prior to the crash.
114
+
The recovery process's job is to read all available WAL segments and replay their data into the in-memory state of the [2PC](index.md#error-handling) transaction manager. Once the replay is complete, the manager state should be restored to what it was prior to the crash.
111
115
112
-
The recovery process runs on PgDog startup and will block it until its complete. Clients will not be able to connect until recovery is complete. Just like the [checkpointer](#checkpointer), it only needs to read WAL segments into memory and doesn't perform any writes to disk, so it's very quick.
116
+
The recovery process runs on PgDog startup and will block it until it's complete. Clients will not be able to connect until recovery is complete. Just like the [checkpointer](#checkpointer), it only needs to read WAL segments into memory and doesn't perform any writes to disk, so it's very quick.
Copy file name to clipboardExpand all lines: docs/features/sharding/2pc/index.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,7 @@ Alternatively, if you're running on managed Postgres (e.g., AWS RDS), this param
31
31
!!! note
32
32
Changes to this parameter require a server restart to take effect.
33
33
34
-
Once prepared transactions are enabled in Postgres, two-phase commit can be enabled in [`pgdog.toml`](../../configuration/pgdog.toml/general.md):
34
+
Once prepared transactions are enabled in Postgres, two-phase commit can be enabled in [`pgdog.toml`](../../../configuration/pgdog.toml/general.md):
35
35
36
36
=== "pgdog.toml"
37
37
```toml
@@ -93,7 +93,7 @@ This feature allows for easier migrations to sharded databases, without requirin
93
93
94
94
While it's often desirable to ensure cross-shard writes are atomic, rewriting single-statement transactions to use 4 statements has some performance overhead. For this reason, this feature is **disabled** by default.
95
95
96
-
If your writes are idempotent and can be safely retried, or your application doesn't have consistency requirements, you don't need to use this. Otherwise, you can enable it in [`pgdog.toml`](../../configuration/pgdog.toml/general.md):
96
+
If your writes are idempotent and can be safely retried, or your application doesn't have consistency requirements, you don't need to use this. Otherwise, you can enable it in [`pgdog.toml`](../../../configuration/pgdog.toml/general.md):
97
97
98
98
=== "pgdog.toml"
99
99
```toml
@@ -112,6 +112,7 @@ Two-phase commit is used for writes only. Read transactions are finished using n
112
112
## Read more
113
113
114
114
{{ next_steps_links([
115
-
("Omnisharded tables", "omnishards.md", "Tables replicated to every shard for fast local joins."),
116
-
("Cross-shard queries", "cross-shard-queries/index.md", "Run queries that span multiple shards transparently."),
115
+
("Crash recovery", "crash-recovery.md", "Recover in-flight two-phase transactions if PgDog crashes."),
116
+
("Omnisharded tables", "../omnishards.md", "Tables replicated to every shard for fast local joins."),
117
+
("Cross-shard queries", "../cross-shard-queries/index.md", "Run queries that span multiple shards transparently."),
Copy file name to clipboardExpand all lines: docs/features/sharding/cross-shard-queries/ddl.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ icon: material/table-cog
8
8
9
9
## Atomicity
10
10
11
-
DDL statements should be atomic across all shards. This is to protect against a single shard failing to create a table or index, which could result in an inconsistent schema. PgDog can use [two-phase commit](../2pc.md) to ensure this is the case, however that means that all DDL statements must be executed inside a transaction, for example:
11
+
DDL statements should be atomic across all shards. This is to protect against a single shard failing to create a table or index, which could result in an inconsistent schema. PgDog can use [two-phase commit](../2pc/index.md) to ensure this is the case, however that means that all DDL statements must be executed inside a transaction, for example:
Copy file name to clipboardExpand all lines: docs/features/sharding/cross-shard-queries/insert.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,7 @@ This is a common pattern for tables that don't have a sharding key, or tables th
31
31
32
32
### Omnisharded consistency
33
33
34
-
Unless [two-phase commit](../2pc.md) is enabled, inserts into omnisharded tables are not guaranteed to be atomic. It is possible for the statement to succeed on some of the shards and not others.
34
+
Unless [two-phase commit](../2pc/index.md) is enabled, inserts into omnisharded tables are not guaranteed to be atomic. It is possible for the statement to succeed on some of the shards and not others.
35
35
36
36
If you don't want to or can't enable two-phase commit on your database shards, consider sending cross-shard inserts inside a transaction or writing idempotent statements, for example:
37
37
@@ -47,7 +47,7 @@ COMMIT;
47
47
This gives you a much higher chance of writing rows on all shards, since you will know if your statement violated a constraint (e.g., unique index or `NOT NULL` check) before committing the transaction.
48
48
49
49
!!! warning "Two-phase commit"
50
-
Enabling [two-phase commit](../2pc.md) is highly recommended. It's been tested and works well in production.
50
+
Enabling [two-phase commit](../2pc/index.md) is highly recommended. It's been tested and works well in production.
51
51
52
52
### Primary keys in omnisharded tables
53
53
@@ -167,7 +167,7 @@ RETURNING id;
167
167
The `id` column will be generated by the database (and not PgDog), globally unique, and matched to the shard it's generated on, as guaranteed by the [sharded sequence](../sequences.md) implementation.
168
168
169
169
!!! warning "Sharded tables only"
170
-
Make sure to **never** use sharded sequences with **omnisharded** tables. They are not guaranteed to generate the same value on all shards, even with [two-phase commit](../2pc.md), and could cause primary key drift across shards.
170
+
Make sure to **never** use sharded sequences with **omnisharded** tables. They are not guaranteed to generate the same value on all shards, even with [two-phase commit](../2pc/index.md), and could cause primary key drift across shards.
171
171
172
172
## Composite primary keys
173
173
@@ -238,4 +238,4 @@ Requiring transactions ensures that if one of the `INSERT` statements fails, e.g
238
238
239
239
!!! warning "Two-phase commit"
240
240
241
-
Much like [omnisharded](#omnisharded-tables) table inserts, it's best to enable [two-phase commit](../2pc.md) before attempting cross-shard multi-tuple inserts. This feature increases the likelihood that cross-shard transactions are atomic.
241
+
Much like [omnisharded](#omnisharded-tables) table inserts, it's best to enable [two-phase commit](../2pc/index.md) before attempting cross-shard multi-tuple inserts. This feature increases the likelihood that cross-shard transactions are atomic.
Copy file name to clipboardExpand all lines: docs/features/sharding/cross-shard-queries/update.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ UPDATE users SET is_admin = true WHERE email LIKE '%@pgdog.dev';
14
14
15
15
## Consistency
16
16
17
-
Much like cross-shard [`INSERT`](insert.md) statements, any updates to multiple rows on multiple databases outside a [two-phase](../2pc.md) transaction are not guaranteed to be atomic. It's always best to send updates inside a transaction, like so:
17
+
Much like cross-shard [`INSERT`](insert.md) statements, any updates to multiple rows on multiple databases outside a [two-phase](../2pc/index.md) transaction are not guaranteed to be atomic. It's always best to send updates inside a transaction, like so:
Copy file name to clipboardExpand all lines: docs/features/sharding/index.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,7 +34,7 @@ PgDog is a query router. It can extract sharding hints directly from the SQL que
34
34
35
35
### Data consistency
36
36
37
-
To make sure data is atomically written in cross-shard transactions, PgDog supports PostgreSQL's prepared transactions and [two-phase commit](2pc.md).
37
+
To make sure data is atomically written in cross-shard transactions, PgDog supports PostgreSQL's prepared transactions and [two-phase commit](2pc/index.md).
Copy file name to clipboardExpand all lines: docs/features/sharding/omnishards.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,7 +52,7 @@ WHERE users.id = $1;
52
52
53
53
### Consistency
54
54
55
-
Writing data to omnisharded tables is atomic if you enable [two-phase commit](2pc.md).
55
+
Writing data to omnisharded tables is atomic if you enable [two-phase commit](2pc/index.md).
56
56
57
57
If you can't or choose not to use 2pc, make sure writes to omnisharded tables can be repeated in case of failure. This can be achieved by using unique indexes and `INSERT ... ON CONFLICT ... DO UPDATE` queries.
0 commit comments