pgdog.git / summary / log / commit / refs

commit    f535adedbdb35b6b6ed595eb0cf61a80dd4549da
Author:   Lev Kokotov <lev.kokotov@gmail.com>
Date:     Wed Feb 05 05:36:17 2025 +0000

    pgDog -> PgDog


README.md | 50 ++++++++++++------------- docs/docs/about.md | 12 +++--- docs/docs/administration/index.md | 16 ++++---- docs/docs/administration/pools.md | 2 +- docs/docs/administration/servers.md | 2 +- docs/docs/architecture/benchmarks.md | 14 +++---- docs/docs/architecture/index.md | 6 +-- docs/docs/configuration/index.md | 14 +++---- docs/docs/configuration/pgdog.toml/admin.md | 2 +- docs/docs/configuration/pgdog.toml/databases.md | 8 ++-- docs/docs/configuration/pgdog.toml/general.md | 22 +++++------ docs/docs/configuration/pgdog.toml/plugins.md | 6 +-- docs/docs/configuration/users.toml/users.md | 12 +++--- docs/docs/features/authentication.md | 18 ++++----- docs/docs/features/healthchecks.md | 8 ++-- docs/docs/features/index.md | 8 ++-- docs/docs/features/load-balancer.md | 4 +- docs/docs/features/plugins/c.md | 6 +-- docs/docs/features/plugins/index.md | 10 ++--- docs/docs/features/plugins/rust.md | 39 ++++++++++--------- docs/docs/features/session-mode.md | 8 ++-- docs/docs/features/sharding/cross-shard.md | 16 ++++---- docs/docs/features/sharding/index.md | 6 +-- docs/docs/features/sharding/manual-routing.md | 4 +- docs/docs/features/transaction-mode.md | 6 +-- docs/docs/index.md | 32 ++++++++-------- pgdog-plugin/README.md | 8 ++-- pgdog.toml | 7 +++- pgdog/src/frontend/client.rs | 8 +++- pgdog/src/frontend/router/parser/insert.rs | 1 + pgdog/src/frontend/router/parser/mod.rs | 1 + pgdog/tests/users.csv | 15 ++++++++ plugins/README.md | 8 ++-- users.toml | 4 +- 34 files changed, 205 insertions(+), 178 deletions(-) diff --git a/README.md b/README.md index dfe9384d..c169f1c9 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# pgDog - Sharding for PostgreSQL +# PgDog - Sharding for PostgreSQL [![Documentation](https://img.shields.io/badge/documentation-blue?style=flat)](https://pgdog.dev) [![CI](https://github.com/levkk/pgdog/actions/workflows/ci.yml/badge.svg)](https://github.com/levkk/pgdog/actions/workflows/ci.yml) -pgDog is a PostgreSQL proxy and transaction pooler that can shard databases. -Spiritual successor to [pgcat](https://github.com/levkk/pgcat) and also written in Rust, pgDog comes with a lot of -classic features like load balancing, failover and connection state management. In addition, pgDog makes improvements to query performance, and adds new features like plugins, cross-shard queries, async protocol support, and `COPY` and logical replication sharding. +PgDog is a PostgreSQL proxy and transaction pooler that can shard databases. +Spiritual successor to [pgcat](https://github.com/levkk/pgcat) and also written in Rust, PgDog comes with a lot of +classic features like load balancing, failover and connection state management. In addition, PgDog makes improvements to query performance, and adds new features like plugins, cross-shard queries, async protocol support, and `COPY` and logical replication sharding. ## Documentation -&#128216; pgDog documentation can be **[found here](https://pgdog.dev).** +&#128216; PgDog documentation can be **[found here](https://pgdog.dev).** ## Features summary @@ -18,10 +18,10 @@ classic features like load balancing, failover and connection state management. | [Load balancer](https://pgdog.dev/features/load-balancer) | Operational | Spread `SELECT` queries across multiple replicas automatically, using algorithms like round robin. | | [Transaction pooling](https://pgdog.dev/features/transaction-mode) | Operational | Identical to pgbouncer, allows for thousands of clients to reuse a handful of server connections. | | [Session pooling](https://pgdog.dev/features/session-mode) | Operational | Exclusive use of server connections for clients needing session-level features. | -| [Plugins](https://pgdog.dev/features/plugins/) | Operational | Control how pgDog routes queries and what results it sends to clients, through loading shared libraries at runtime. | +| [Plugins](https://pgdog.dev/features/plugins/) | Operational | Control how PgDog routes queries and what results it sends to clients, through loading shared libraries at runtime. | | [Sharding](https://pgdog.dev/features/sharding/) | Work in progress | Automatically split data and queries between multiple databases, scaling writes horizonally. | | [Authentication](https://pgdog.dev/features/authentication/) | Supports `scram-sha-256` and `trust` | Suppport for various PostgreSQL authentication mechanisms, like SCRAM, MD5, and LDAP. | -| [Configuration](https://pgdog.dev/configuration/) | Operational | Configure pgDog without restarting the pooler or breaking connections. | +| [Configuration](https://pgdog.dev/configuration/) | Operational | Configure PgDog without restarting the pooler or breaking connections. | ## Getting started @@ -37,7 +37,7 @@ performance benchmarks. ### Configuration -pgDog has two configuration files: +PgDog has two configuration files: * `pgdog.toml` which contains general settings and PostgreSQL servers information * `users.toml` for users and passwords @@ -73,15 +73,15 @@ CREATE DATABASE pgdog; CREATE USER pgdog PASSWORD 'pgdog' LOGIN; ``` -### Running pgDog +### Running PgDog -Running pgDog can be done with Cargo: +Running PgDog can be done with Cargo: ```bash cargo run --release ``` -You can connect to pgDog with psql or any other PostgreSQL client: +You can connect to PgDog with psql or any other PostgreSQL client: ```bash psql postgres://pgdog:pgdog@127.0.0.1:6432/pgdog @@ -91,13 +91,13 @@ psql postgres://pgdog:pgdog@127.0.0.1:6432/pgdog ### Load balancer -pgDog is an application layer (OSI Level 7) load balancer for PostgreSQL. It can proxy multiple replicas (and primary) and distribute transactions. It comes with support for multiple strategies, including round robin and random. Additionally, it can parse queries and send `SELECT` queries to replicas and all others to the primary. This allows to proxy all databases behind a single pgDog deployment. +PgDog is an application layer (OSI Level 7) load balancer for PostgreSQL. It can proxy multiple replicas (and primary) and distribute transactions. It comes with support for multiple strategies, including round robin and random. Additionally, it can parse queries and send `SELECT` queries to replicas and all others to the primary. This allows to proxy all databases behind a single PgDog deployment. &#128216; **[Load balancer](https://pgdog.dev/features/load-balancer)** #### Healthchecks and failover -pgDog maintains a real time list of healthy hosts in its database configuration. +PgDog maintains a real time list of healthy hosts in its database configuration. When a host fails a healthcheck, it's removed from active rotation and queries are rerouted to other replicas. This is analogous to modern HTTP load balancing, except it's at the database layer. @@ -108,14 +108,14 @@ Failover maximizes database availability and protects against intermittent issue ### Transaction pooling -Like pgbouncer, pgDog supports transaction-level connection pooling, allowing +Like pgbouncer, PgDog supports transaction-level connection pooling, allowing 1000s (even 100,000s) of clients to reuse just a few PostgreSQL server connections. &#128216; **[Transactions](https://pgdog.dev/features/transaction-mode)** ### Plugins -pgDog comes with its own plugin system that loads them at runtime using a shared library interface. +PgDog comes with its own plugin system that loads them at runtime using a shared library interface. If a plugin can expose a predefined C API, it can be written in any language, including C/C++, Rust, Zig, Go, Python, Ruby, Java, and many more. Plugins can be used to route queries to specific databases in a sharded configuration, or to @@ -131,7 +131,7 @@ Examples of plugins can be found in [examples](https://github.com/levkk/pgdog/tr _This feature is a work in progress._ -pgDog is able to handle databases with multiple shards by routing queries automatically to one or more shards. The `pgdog-routing` plugin parses +PgDog is able to handle databases with multiple shards by routing queries automatically to one or more shards. The `pgdog-routing` plugin parses queries, extracts tables and columns information, and calculates which shard(s) the query should go to based on the parameters. Not all operations are supported, but a lot of common use cases are working. @@ -149,7 +149,7 @@ GRANT CONNECT ON DATABASE shard_0 TO pgdog; GRANT CONNECT ON DATABASE shard_1 TO pgdog; ``` -You can launch pgDog with the sharded configuration using the files provided in the repository: +You can launch PgDog with the sharded configuration using the files provided in the repository: ```bash cargo run -- --config pgdog-sharded.toml --users users-sharded.toml @@ -157,7 +157,7 @@ cargo run -- --config pgdog-sharded.toml --users users-sharded.toml ### Configuration -pgDog is highly configurable and many aspects of its operation can be tweaked at runtime, without having +PgDog is highly configurable and many aspects of its operation can be tweaked at runtime, without having to restart the process and break PostgreSQL connections. If you've used pgbouncer (or pgcat) before, the options will be familiar. If not, options are documented with examples. @@ -165,13 +165,13 @@ will be familiar. If not, options are documented with examples. ## &#128678; Status &#128678; -While a lot of "classic" features of pgDog, like load balancing and healthchecks, have been well tested in production and at scale, the current codebase has not. This project is just getting started and early adopters are welcome to try pgDog internally. +While a lot of "classic" features of PgDog, like load balancing and healthchecks, have been well tested in production and at scale, the current codebase has not. This project is just getting started and early adopters are welcome to try PgDog internally. Status on features stability will be [updated regularly](https://pgdog.dev/features/). ## Performance -pgDog does its best to minimize its impact on overall database performance. Using Rust and Tokio is a great start for a fast network proxy, but additional +PgDog does its best to minimize its impact on overall database performance. Using Rust and Tokio is a great start for a fast network proxy, but additional care is also taken to perform as few operations as possible while moving data between client and server sockets. Some benchmarks are provided to help set a baseline. @@ -179,17 +179,17 @@ to help set a baseline. ## License -pgDog is free and open source software, licensed under the AGPL v3. While often misunderstood, this license is very permissive +PgDog is free and open source software, licensed under the AGPL v3. While often misunderstood, this license is very permissive and allows the following without any additional requirements from you or your organization: * Internal use * Private modifications for internal use without sharing any source code -You can freely use pgDog to power your PostgreSQL databases without having to -share any source code, including proprietary work product or any pgDog modifications you make. +You can freely use PgDog to power your PostgreSQL databases without having to +share any source code, including proprietary work product or any PgDog modifications you make. -AGPL was written specifically for organizations that offer pgDog _as a public service_ (e.g. database cloud providers) and require -those organizations to share any modifications they make to pgDog, including new features and bug fixes. +AGPL was written specifically for organizations that offer PgDog _as a public service_ (e.g. database cloud providers) and require +those organizations to share any modifications they make to PgDog, including new features and bug fixes. ## Contributions diff --git a/docs/docs/about.md b/docs/docs/about.md index 340900ad..d258c348 100644 --- a/docs/docs/about.md +++ b/docs/docs/about.md @@ -6,14 +6,14 @@ Contributions in all forms are welcome. If you find a bug and want to provide a create an issue first to discuss. ## License -pgDog is free and open source software licensed under the [AGPL-3.0](https://en.wikipedia.org/wiki/GNU_Affero_General_Public_License) license. While often misunderstood, this license allows anyone to use -pgDog internally without sharing source code or any other work related to pgDog operations. +PgDog is free and open source software licensed under the [AGPL-3.0](https://en.wikipedia.org/wiki/GNU_Affero_General_Public_License) license. While often misunderstood, this license allows anyone to use +PgDog internally without sharing source code or any other work related to PgDog operations. -All [plugins](features/plugins/index.md) developed for pgDog can be licensed under any license you wish and distributed to anyone (or kept private). +All [plugins](features/plugins/index.md) developed for PgDog can be licensed under any license you wish and distributed to anyone (or kept private). -If you plan to offer pgDog as a public service (e.g. a database cloud offering), please make sure to share any modifications you make to -pgDog source code, so the whole community can benefit from your knowledge and expertise. +If you plan to offer PgDog as a public service (e.g. a database cloud offering), please make sure to share any modifications you make to +PgDog source code, so the whole community can benefit from your knowledge and expertise. ## Project name -This project is dedicated to the bestest dog in the world who's been patiently sitting at my feet the entire time pgDog has been developed. +This project is dedicated to the bestest dog in the world who's been patiently sitting at my feet the entire time PgDog has been developed. diff --git a/docs/docs/administration/index.md b/docs/docs/administration/index.md index 77901a91..43e03827 100644 --- a/docs/docs/administration/index.md +++ b/docs/docs/administration/index.md @@ -1,9 +1,9 @@ # Administration overview -pgDog keeps track of clients, servers and connection pools. It provides real time statistics on its internal operations for system +PgDog keeps track of clients, servers and connection pools. It provides real time statistics on its internal operations for system administrators to keep track of and integrate with monitoring tools like Datadog. -Just like pgbouncer, pgDog has a special "admin" database clients can connect to and run custom SQL commands +Just like pgbouncer, PgDog has a special "admin" database clients can connect to and run custom SQL commands to get statistics. ## Admin database @@ -14,8 +14,8 @@ The admin database name is [configurable](../configuration/pgdog.toml/admin.md). | Command | Description | |---------|-------------| -| [`SHOW CLIENTS`](clients.md) | Clients connected to pgDog with real time statistics. | -| [`SHOW SERVERS`](servers.md) | Server connections made by pgDog to PostgreSQL. | +| [`SHOW CLIENTS`](clients.md) | Clients connected to PgDog with real time statistics. | +| [`SHOW SERVERS`](servers.md) | Server connections made by PgDog to PostgreSQL. | | [`SHOW POOLS`](pools.md) | Connection pools used to multiplex clients and servers. | | [`SHOW CONFIG`](config.md) | Currently loaded values from `pgdog.toml`. | | `RELOAD` | Reload configuration from disk. See [pgdog.toml](../configuration/pgdog.toml/general.md) and [users.toml](../configuration/users.toml/users.md) for which options can be changed at runtime. | @@ -23,12 +23,12 @@ The admin database name is [configurable](../configuration/pgdog.toml/admin.md). | `PAUSE` | Pause all pools. Clients will wait for connections until pools are resumed. Can be used for gracefully restarting PostgreSQL servers. | | `RESUME` | Resume all pools. Clients are able to check out connections again. | -## Shutting down pgDog +## Shutting down PgDog -When you need to shutdown pgDog, e.g. to deploy a new version, you can do so gracefully by issuing `SIGINT` (e.g. Ctrl-C) to the `pgdog` process. -pgDog will stop listening for new connections and give connected clients some time to finish their transactions and disconnect. +When you need to shutdown PgDog, e.g. to deploy a new version, you can do so gracefully by issuing `SIGINT` (e.g. Ctrl-C) to the `pgdog` process. +PgDog will stop listening for new connections and give connected clients some time to finish their transactions and disconnect. -The amount of time pgDog will wait is [configurable](../configuration/pgdog.toml/general.md#shutdown_timeout). By default, pgDog will wait 60 seconds. +The amount of time PgDog will wait is [configurable](../configuration/pgdog.toml/general.md#shutdown_timeout). By default, PgDog will wait 60 seconds. #### Example diff --git a/docs/docs/administration/pools.md b/docs/docs/administration/pools.md index df94851e..584d9ca5 100644 --- a/docs/docs/administration/pools.md +++ b/docs/docs/administration/pools.md @@ -1,6 +1,6 @@ # Pools -`SHOW POOLS` is a command to show real time statistics on connection pools used to [multiplex](../features/transaction-mode.md) pgDog clients and PostgreSQL servers. For example: +`SHOW POOLS` is a command to show real time statistics on connection pools used to [multiplex](../features/transaction-mode.md) PgDog clients and PostgreSQL servers. For example: ``` admin=> \x diff --git a/docs/docs/administration/servers.md b/docs/docs/administration/servers.md index 76464cd0..3a7841f8 100644 --- a/docs/docs/administration/servers.md +++ b/docs/docs/administration/servers.md @@ -44,7 +44,7 @@ age | 1719734 | `state` | Server connection state, e.g. `active`, `idle in transaction`, etc. | | `transactions` | Number of transactions completed by this server connection. | | `queries` | Number of queries executed by this server connection. | -| `rollbacks` | Number of automatic rollbacks executed on this server connection by pgDog to clean up after idle transactions left by clients. | +| `rollbacks` | Number of automatic rollbacks executed on this server connection by PgDog to clean up after idle transactions left by clients. | | `prepared_statements` | Number of prepared statements created on this server connection. | | `healthchecks` | Number of healthchecks executed on this server connection. | | `errors` | Number of errors this connection has produced e.g. syntax errors. | diff --git a/docs/docs/architecture/benchmarks.md b/docs/docs/architecture/benchmarks.md index 82c74417..10415377 100644 --- a/docs/docs/architecture/benchmarks.md +++ b/docs/docs/architecture/benchmarks.md @@ -1,8 +1,8 @@ # Benchmarks -pgDog does its best to minimize its impact on database performance. Great care is taken to make sure as few operations are possible are performed +PgDog does its best to minimize its impact on database performance. Great care is taken to make sure as few operations are possible are performed when passing data between clients and servers. All benchmarks listed below were done on my local system and should be taken with a grain of salt. -Real world performance is impacted by factors like network speed, query complexity and especially by hardware used for running pgDog and PostgreSQL servers. +Real world performance is impacted by factors like network speed, query complexity and especially by hardware used for running PgDog and PostgreSQL servers. ## pgbench @@ -13,13 +13,13 @@ $ pgbench --version pgbench (PostgreSQL) 16.4 (Postgres.app) ``` -A standard pgBench benchmark will run `INSERT`, `UPDATE`, `SELECT` and `DELETE` queries to get an overall view of database performance. Since we are only testing the performance of pgDog, we are going to run `SELECT` queries only and minimize the impact of hard disk I/O on this test. +A standard pgBench benchmark will run `INSERT`, `UPDATE`, `SELECT` and `DELETE` queries to get an overall view of database performance. Since we are only testing the performance of PgDog, we are going to run `SELECT` queries only and minimize the impact of hard disk I/O on this test. This benchmark can be reproduced by passing the `-S` flag to `pgbench`. The results below were performed using the configuration found in [`pgdog.toml`](https://github.com/levkk/pgdog/blob/main/pgdog.toml). ### Results -Numbers below are for a single primary benchmark in transaction mode. No plugins are in use and pgDog is configured to use only 1 CPU core (`workers = 0`). +Numbers below are for a single primary benchmark in transaction mode. No plugins are in use and PgDog is configured to use only 1 CPU core (`workers = 0`). | Clients | Throughput (/s) | Latency | |---------|--------------|------------| @@ -47,7 +47,7 @@ has some noticeable overhead. Enabling multi-threading improved performance by o #### 1 client Benchmarks with `-c 1` (1 client) are a good baseline for what's possible under the best possible circumstances. There is no contention on resources -and pgDog effectively receives data in one socket and pushes it out the other. +and PgDog effectively receives data in one socket and pushes it out the other. #### 10 clients @@ -56,11 +56,11 @@ has to serve clients without any slack in the system. This benchmark should prod #### 100 clients -With over 10x more clients connected than available servers, connections are fighting for resources and pgDog has to make sure everyone gets served in a fair way. Consistent throughput in this benchmark demonstrates our ability to timeshare server connections effectively. +With over 10x more clients connected than available servers, connections are fighting for resources and PgDog has to make sure everyone gets served in a fair way. Consistent throughput in this benchmark demonstrates our ability to timeshare server connections effectively. ### In the real world -In production, PostgreSQL clients are expected to be mostly idle. For example, web applications spend a lot of their time parsing HTTP requests, running code and waiting on network I/O. This leaves plenty of time for pgDog (and PostgreSQL) to serve queries for thousands of clients. +In production, PostgreSQL clients are expected to be mostly idle. For example, web applications spend a lot of their time parsing HTTP requests, running code and waiting on network I/O. This leaves plenty of time for PgDog (and PostgreSQL) to serve queries for thousands of clients. #### Hardware impact diff --git a/docs/docs/architecture/index.md b/docs/docs/architecture/index.md index d4f76a07..1d42dceb 100644 --- a/docs/docs/architecture/index.md +++ b/docs/docs/architecture/index.md @@ -1,15 +1,15 @@ # Architecture overview -pgDog is written in the [Rust](https://rust-lang.org) programming language. It is also asynchronous, powered by the [Tokio](https://tokio.rs) runtime. This allows pgDog to serve hundreds of thousands of connections on one machine and to take advantage of multiple CPUs. +PgDog is written in the [Rust](https://rust-lang.org) programming language. It is also asynchronous, powered by the [Tokio](https://tokio.rs) runtime. This allows PgDog to serve hundreds of thousands of connections on one machine and to take advantage of multiple CPUs. ## Plugins [Plugins](../features/plugins/index.md) are shared libraries (`.so` on Linux, `.dylib` on Mac, `.dll` on Windows) loaded at startup. This allows to -change many aspects of pgDog functionality without altering or recompiling internal source code. +change many aspects of PgDog functionality without altering or recompiling internal source code. ## PostgreSQL protocol -pgDog speaks the PostgreSQL [frontend/backend](https://www.postgresql.org/docs/current/protocol.html) protocol. This allows it to act as an +PgDog speaks the PostgreSQL [frontend/backend](https://www.postgresql.org/docs/current/protocol.html) protocol. This allows it to act as an application layer (OSI Level 7) proxy and multiplex client/server connections. It can also alter connection state to suit operational needs, e.g. rolling back unfinished transactions, changing server settings, clearing session variables. diff --git a/docs/docs/configuration/index.md b/docs/docs/configuration/index.md index 3d6c38ad..7b46fea1 100644 --- a/docs/docs/configuration/index.md +++ b/docs/docs/configuration/index.md @@ -1,13 +1,13 @@ # Configuration overview -pgDog uses the [TOML](https://toml.io/en/) configuration language for its two configuration files: `pgdog.toml` and `users.toml`. Both are required for pgDog to run, but most settings are optional with sane defaults, so a basic pgDog deployment requires very little work to configure. +PgDog uses the [TOML](https://toml.io/en/) configuration language for its two configuration files: `pgdog.toml` and `users.toml`. Both are required for PgDog to run, but most settings are optional with sane defaults, so a basic PgDog deployment requires very little work to configure. -By default, pgDog looks for both configuration files in the current working directory. Alternatively, you can pass -`--config=<path>` and `--users=<path>` arguments to pgDog on startup. +By default, PgDog looks for both configuration files in the current working directory. Alternatively, you can pass +`--config=<path>` and `--users=<path>` arguments to PgDog on startup. ## Hot reload -Most settings can be reloaded without restarting pgDog. This allows to tweak them at runtime without breaking client or server connections. For settings that require a restart, a note is added to the documentation. +Most settings can be reloaded without restarting PgDog. This allows to tweak them at runtime without breaking client or server connections. For settings that require a restart, a note is added to the documentation. ## Units @@ -17,14 +17,14 @@ To make things simpler, all units of time are in milliseconds. For example, if y checkout_timeout = 5_000 ``` -Since pgDog uses TOML, both `5000` and `5_000` are valid numbers. Configuration will fail to load if non-integer values are used, e.g. "5s" or "53.5". +Since PgDog uses TOML, both `5000` and `5_000` are valid numbers. Configuration will fail to load if non-integer values are used, e.g. "5s" or "53.5". ## Overview | Name | Description | |------|-------------| | [General](pgdog.toml/general.md) | General pooler settings like `host`, `port` and various timeouts. | -| [Databases](pgdog.toml/databases.md) | PostgreSQL databases proxied by pgDog. | +| [Databases](pgdog.toml/databases.md) | PostgreSQL databases proxied by PgDog. | | [Plugins](pgdog.toml/plugins.md) | Plugins configuration. | -| [Users](users.toml/users.md) | List of users (with passwords) that are allowed to connect to pgDog. | +| [Users](users.toml/users.md) | List of users (with passwords) that are allowed to connect to PgDog. | | [Admin](pgdog.toml/admin.md) | Admin database settings like admin password. | diff --git a/docs/docs/configuration/pgdog.toml/admin.md b/docs/docs/configuration/pgdog.toml/admin.md index f9093e95..c2599947 100644 --- a/docs/docs/configuration/pgdog.toml/admin.md +++ b/docs/docs/configuration/pgdog.toml/admin.md @@ -1,7 +1,7 @@ # Admin database settings Admin database settings control access to the [admin](../../administration/index.md) database which contains real time statistics about internal operations -of pgDog. For example: +of PgDog. For example: ```toml [admin] diff --git a/docs/docs/configuration/pgdog.toml/databases.md b/docs/docs/configuration/pgdog.toml/databases.md index ce71a382..b41b44eb 100644 --- a/docs/docs/configuration/pgdog.toml/databases.md +++ b/docs/docs/configuration/pgdog.toml/databases.md @@ -1,6 +1,6 @@ # Database settings -Database settings configure which databases pgDog is proxying. This is a TOML list of hosts, ports, and other settings like database roles (primary or replica). For each database host, add a `[[databases]]` entry to `pgdog.toml`. For example: +Database settings configure which databases PgDog is proxying. This is a TOML list of hosts, ports, and other settings like database roles (primary or replica). For each database host, add a `[[databases]]` entry to `pgdog.toml`. For example: ```toml [[databases]] @@ -17,7 +17,7 @@ role = "replica" ### `name` -Name of your database. Clients that connect to pgDog will need to use this name to refer to the database. For multiple entries part of +Name of your database. Clients that connect to PgDog will need to use this name to refer to the database. For multiple entries part of the same cluster, use the same `name`. Default: **none** (required) @@ -48,13 +48,13 @@ Default: **`primary`** ### `database_name` -Name of the PostgreSQL database on the server pgDog will connect to. If not set, this defaults to `name`. +Name of the PostgreSQL database on the server PgDog will connect to. If not set, this defaults to `name`. Default: **none** (defaults to `name`) ### `user` -Name of the PostgreSQL user to connect with when creating backend connections from pgDog to Postgres. If not set, this defaults to `name` in [`users.toml`](../users.toml/users.md). This setting is used to override `users.toml` configuration values. +Name of the PostgreSQL user to connect with when creating backend connections from PgDog to Postgres. If not set, this defaults to `name` in [`users.toml`](../users.toml/users.md). This setting is used to override `users.toml` configuration values. Default: **none** (see [`users.toml`](../users.toml/users.md)) diff --git a/docs/docs/configuration/pgdog.toml/general.md b/docs/docs/configuration/pgdog.toml/general.md index e29e8360..bf8137f4 100644 --- a/docs/docs/configuration/pgdog.toml/general.md +++ b/docs/docs/configuration/pgdog.toml/general.md @@ -5,7 +5,7 @@ General settings are relevant to the operations of the pooler itself, or apply t ### `host` -The IP address of the local network interface pgDog will bind to listen for connections. +The IP address of the local network interface PgDog will bind to listen for connections. !!! note This setting cannot be changed at runtime. @@ -14,7 +14,7 @@ Default: **`0.0.0.0`** (all interfaces) ### `port` -The TCP port pgDog will bind to listen for connections. +The TCP port PgDog will bind to listen for connections. Default: **`6432`** @@ -55,7 +55,7 @@ Default: **`transaction`** ### `tls_certificate` -Path to the TLS certificate pgDog will use to setup TLS connections with clients. If none is provided, TLS will be disabled. +Path to the TLS certificate PgDog will use to setup TLS connections with clients. If none is provided, TLS will be disabled. Default: **none** @@ -64,7 +64,7 @@ Default: **none** ### `tls_private_key` -Path to the TLS private key pgDog will use to setup TLS connections with clients. If none is provided, TLS will be disabled. +Path to the TLS private key PgDog will use to setup TLS connections with clients. If none is provided, TLS will be disabled. Default: **none** @@ -75,30 +75,30 @@ Default: **none** ### `healthcheck_interval` -Frequency of healthchecks performed by pgDog to ensure connections provided to clients from the pool are working. +Frequency of healthchecks performed by PgDog to ensure connections provided to clients from the pool are working. Default: **`30_000`** (30s) ### `idle_healthcheck_interval` -Frequency of healthchecks performed by pgDog on idle connections. This ensures the database is checked for health periodically when -pgDog receives little to no client requests. +Frequency of healthchecks performed by PgDog on idle connections. This ensures the database is checked for health periodically when +PgDog receives little to no client requests. Default: **`30_000`** (30s) #### Note on `min_pool_size` -[Healthchecks](../../features/healthchecks.md) try to use existing idle connections to validate the database is up and running. If there are no idle connections available, pgDog will create an ephemeral connection to perform the healthcheck. If you want to avoid this, make sure to have `min_pool_size` to be at least `1`. +[Healthchecks](../../features/healthchecks.md) try to use existing idle connections to validate the database is up and running. If there are no idle connections available, PgDog will create an ephemeral connection to perform the healthcheck. If you want to avoid this, make sure to have `min_pool_size` to be at least `1`. ### `idle_healthcheck_delay` -Delay running idle healthchecks at pgDog startup to give databases (and pools) time to spin up. +Delay running idle healthchecks at PgDog startup to give databases (and pools) time to spin up. Default: **`5_000`** (5s) ## Timeouts -These settings control how long pgDog waits for maintenance tasks to complete. These timeouts make sure pgDog can recover +These settings control how long PgDog waits for maintenance tasks to complete. These timeouts make sure PgDog can recover from abnormal conditions like hardware failure. ### `rollback_timeout` @@ -116,7 +116,7 @@ Default: **`300_000`** (5 minutes) ### `shutdown_timeout` -How long to wait for active clients to finish transactions when shutting down. This ensures that pgDog redeployments disrupt as few +How long to wait for active clients to finish transactions when shutting down. This ensures that PgDog redeployments disrupt as few queries as possible. Default: **`60_000`** (60s) diff --git a/docs/docs/configuration/pgdog.toml/plugins.md b/docs/docs/configuration/pgdog.toml/plugins.md index 80b52fbb..8090d151 100644 --- a/docs/docs/configuration/pgdog.toml/plugins.md +++ b/docs/docs/configuration/pgdog.toml/plugins.md @@ -14,10 +14,10 @@ name = "alice_router" ``` !!! note - Plugins can only be configured at pgDog startup. They cannot be changed after + Plugins can only be configured at PgDog startup. They cannot be changed after the process is running. ### **`name`** -Name of the plugin to load. This is used by pgDog to look up the shared library object in [`LD_LIBRARY_PATH`](https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html). For example, if your plugin -name is `router`, pgDog will look for `librouter.so` on Linux, `librouter.dll` on Windows and `librouter.dylib` on Mac OS. +Name of the plugin to load. This is used by PgDog to look up the shared library object in [`LD_LIBRARY_PATH`](https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html). For example, if your plugin +name is `router`, PgDog will look for `librouter.so` on Linux, `librouter.dll` on Windows and `librouter.dylib` on Mac OS. diff --git a/docs/docs/configuration/users.toml/users.md b/docs/docs/configuration/users.toml/users.md index 2027e52b..f4c7d547 100644 --- a/docs/docs/configuration/users.toml/users.md +++ b/docs/docs/configuration/users.toml/users.md @@ -1,6 +1,6 @@ # Users configuration -This configuration controls which users are allowed to connect to pgDog. This is a TOML list so for each user, add a `[[users]]` section to `users.toml`. For example: +This configuration controls which users are allowed to connect to PgDog. This is a TOML list so for each user, add a `[[users]]` section to `users.toml`. For example: ```toml [[users]] @@ -17,7 +17,7 @@ password = "opensesame" ### `name` -Name of the user. Clients that connect to pgDog will need to use this username. +Name of the user. Clients that connect to PgDog will need to use this username. Default: **none** (required) @@ -29,7 +29,7 @@ Default: **none** (required) ### `password` -The password for the user. Clients will need to provide this when connecting to pgDog. +The password for the user. Clients will need to provide this when connecting to PgDog. Default: **none** (required) @@ -42,13 +42,13 @@ Default: **none** (defaults to `default_pool_size` from `pgdog.toml`) ### `pooler_mode` Overrides [`pooler_mode`](../pgdog.toml/general.md) for this user. This allows users in [session mode](../../features/session-mode.md) to connect to the -same pgDog instance as users in [transaction mode](../../features/transaction-mode.md). +same PgDog instance as users in [transaction mode](../../features/transaction-mode.md). Default: **none** (defaults to `pooler_mode` from `pgdog.toml`) ### `server_user` -Which user to connect with when creating backend connections from pgDog to PostgreSQL. By default, the user configured in `name` is used. This setting allows to override this configuration and use a different user. +Which user to connect with when creating backend connections from PgDog to PostgreSQL. By default, the user configured in `name` is used. This setting allows to override this configuration and use a different user. !!! note Values specified in `pgdog.toml` take priority over this configuration. @@ -57,7 +57,7 @@ Default: **none** (defaults to `name`) ### `server_password` -Which password to connect with when creating backend connections from pgDog to PostgreSQL. By default, the password configured in `password` is used. This setting allows to override this configuration and use a different password, decoupling server passwords from user passwords given to clients. +Which password to connect with when creating backend connections from PgDog to PostgreSQL. By default, the password configured in `password` is used. This setting allows to override this configuration and use a different password, decoupling server passwords from user passwords given to clients. Default: **none** (defaults to `password`) diff --git a/docs/docs/features/authentication.md b/docs/docs/features/authentication.md index 98ab988f..dbc260bd 100644 --- a/docs/docs/features/authentication.md +++ b/docs/docs/features/authentication.md @@ -1,9 +1,9 @@ # Authentication -PostgreSQL servers support many authentication mechanisms. pgDog supports a subset of those, with the aim to support all of them over time. Since PostgreSQL 14, `SCRAM-SHA-256` is widely used to encrypt passwords and pgDog supports this algorithm for both client and server connections. +PostgreSQL servers support many authentication mechanisms. PgDog supports a subset of those, with the aim to support all of them over time. Since PostgreSQL 14, `SCRAM-SHA-256` is widely used to encrypt passwords and PgDog supports this algorithm for both client and server connections. -Authentication is **enabled** by default. Applications connecting to pgDog must provide a username and password which is [configured](../configuration/users.toml/users.md) in `users.toml`. For connecting to PostgreSQL databases, -pgDog currently supports only `SCRAM-SHA-256`. +Authentication is **enabled** by default. Applications connecting to PgDog must provide a username and password which is [configured](../configuration/users.toml/users.md) in `users.toml`. For connecting to PostgreSQL databases, +PgDog currently supports only `SCRAM-SHA-256`. ## Add users @@ -17,32 +17,32 @@ database = "pgdog" password = "hunter2" ``` -pgDog will expect clients connecting as `pgdog` to provide the password `hunter2` (hashed with `SCRAM-SHA-256`), and will use the same username and password to connect to PostgreSQL. +PgDog will expect clients connecting as `pgdog` to provide the password `hunter2` (hashed with `SCRAM-SHA-256`), and will use the same username and password to connect to PostgreSQL. #### Override server credentials You can override the user and/or -password pgDog uses to connect to Postgres by specifying `server_user` and `server_password` in the same configuration: +password PgDog uses to connect to Postgres by specifying `server_user` and `server_password` in the same configuration: ```toml server_user = "bob" server_password = "opensesame" ``` -This allows to separate client and server credentials. In case your clients accidentally leak theirs, you only need to rotate them in the pgDog configuration, without having to take downtime to change passwords in PostgreSQL. +This allows to separate client and server credentials. In case your clients accidentally leak theirs, you only need to rotate them in the PgDog configuration, without having to take downtime to change passwords in PostgreSQL. ## Passthrough authentication !!! note This feature is a work in progress. -Passthrough authentication is a feature where instead of storing passwords in `users.toml`, pgDog connects to the database server and queries it for the password stored in `pg_shadow`. It then matches +Passthrough authentication is a feature where instead of storing passwords in `users.toml`, PgDog connects to the database server and queries it for the password stored in `pg_shadow`. It then matches this password to what the user supplied, and if they match, authorizes the connection. -Passthrough authentication simplifies pgDog deployments by using a single source of truth for authentication. +Passthrough authentication simplifies PgDog deployments by using a single source of truth for authentication. Currently, passthrough authentication is a work-in-progress. You can track progress in [issue #6](https://github.com/levkk/pgdog/issues/6). ## Security -Since pgDog stores passwords in a separate configuration file, it's possible to encrypt it at rest without compromising the DevOps experience. For example, Kubernetes provides built-in [secrets management](https://kubernetes.io/docs/concepts/configuration/secret/) to manage this. +Since PgDog stores passwords in a separate configuration file, it's possible to encrypt it at rest without compromising the DevOps experience. For example, Kubernetes provides built-in [secrets management](https://kubernetes.io/docs/concepts/configuration/secret/) to manage this. diff --git a/docs/docs/features/healthchecks.md b/docs/docs/features/healthchecks.md index 0122cfb8..7acdce36 100644 --- a/docs/docs/features/healthchecks.md +++ b/docs/docs/features/healthchecks.md @@ -1,10 +1,10 @@ # Healthchecks -Databases proxied by pgDog are regularly checked with healthchecks. A healthcheck is a simple query, e.g. +Databases proxied by PgDog are regularly checked with healthchecks. A healthcheck is a simple query, e.g. `SELECT 1`, which ensures the database is reachable and able to answer requests. If a database fails a healthcheck, it's placed in a list of banned hosts. Banned databases are removed -from the load balancer and will not serve transactions. This allows pgDog to reduce errors clients see +from the load balancer and will not serve transactions. This allows PgDog to reduce errors clients see when a database fails, for example due to hardware issues. <center> @@ -30,7 +30,7 @@ healthcheck_interval = 60_000 # ms ### Timeouts -By default, pgDog gives the database **5 seconds** to answer a healthcheck. If it doesn't receive a reply, +By default, PgDog gives the database **5 seconds** to answer a healthcheck. If it doesn't receive a reply, the database will be banned from serving traffic for a configurable amount of time. Both the healthcheck timeout and the ban time are configurable. @@ -48,7 +48,7 @@ issues, like network connectivity, to resolve themselves without manual interven ### Failsafe -If all databases in a cluster are banned due to a healthcheck failure, pgDog assumes that healthchecks +If all databases in a cluster are banned due to a healthcheck failure, PgDog assumes that healthchecks are returning incorrect information and unbans all databases in the cluster. This protects against false positives and ensures the cluster continues to serve traffic. diff --git a/docs/docs/features/index.md b/docs/docs/features/index.md index 99deef96..b6d4309a 100644 --- a/docs/docs/features/index.md +++ b/docs/docs/features/index.md @@ -1,6 +1,6 @@ # Features overview -pgDog contains multiple foundational and unique features which make it a great choice +PgDog contains multiple foundational and unique features which make it a great choice for modern PostgreSQL deployments. Most features are configurable and can be toggled and tuned. Experimental features are marked @@ -11,7 +11,7 @@ load balancing, healthchecks, and query routing have been battle-tested and work !!! note - pgDog is just getting started and most features are incomplete. The documentation + PgDog is just getting started and most features are incomplete. The documentation is sometimes written to reflect the desired state. In the case where the feature is not complete, a note is added to that effect. @@ -20,7 +20,7 @@ load balancing, healthchecks, and query routing have been battle-tested and work | [Transaction mode](transaction-mode.md) | Multiplex transactions and servers for busy PostgreSQL deployments. | ✔️ Good | | [Load balancer](load-balancer.md) | Split query traffic evenly across multiple databases. | 🔨 Work in progress | | [Healthchecks](healthchecks.md) | Periodically check databases to ensure they are up and can serve queries. | ✔️ Good | -| [Live configuration reloading](../configuration/index.md) | Update configuration at runtime without having to restart pgDog. | 🔨 Work in progress | +| [Live configuration reloading](../configuration/index.md) | Update configuration at runtime without having to restart PgDog. | 🔨 Work in progress | | [Sharding](sharding/index.md) | Automatic query routing using a sharding key to scale writes horizontally. | 🔨 Work in progress | | [Plugins](plugins/index.md) | Pluggable libraries to parse and route queries, loaded at runtime. | ✔️ Good | | [Authentication](authentication.md) | Support for various PostgreSQL authentication mechanisms, e.g. `SCRAM-SHA-256`. | 🔨 Work in progress | @@ -28,4 +28,4 @@ load balancing, healthchecks, and query routing have been battle-tested and work ## OS support -pgDog doesn't use any OS-specific features and should run on all systems supported by the Rust compiler, e.g. Linux (x86 and ARM64), Mac OS, and Windows. +PgDog doesn't use any OS-specific features and should run on all systems supported by the Rust compiler, e.g. Linux (x86 and ARM64), Mac OS, and Windows. diff --git a/docs/docs/features/load-balancer.md b/docs/docs/features/load-balancer.md index 52e52684..970b888a 100644 --- a/docs/docs/features/load-balancer.md +++ b/docs/docs/features/load-balancer.md @@ -1,6 +1,6 @@ # Load balancer -pgDog operates at the application layer (OSI Level 7) and is capable of load balancing queries across +PgDog operates at the application layer (OSI Level 7) and is capable of load balancing queries across multiple PostgreSQL databases. <center> @@ -27,7 +27,7 @@ This strategy is used by **default**. ### Least active connections -pgDog keeps track of how many active connections each database has and can route queries to databases +PgDog keeps track of how many active connections each database has and can route queries to databases which are least busy executing requests. This allows to "bin pack" the cluster based on how seemingly active (or inactive) the databases are. diff --git a/docs/docs/features/plugins/c.md b/docs/docs/features/plugins/c.md index 3b74cc5f..9b6681a0 100644 --- a/docs/docs/features/plugins/c.md +++ b/docs/docs/features/plugins/c.md @@ -1,6 +1,6 @@ # Plugins in C -Writing pgDog plugins in C is pretty straight forward if you're comfortable in the language. The plugin API +Writing PgDog plugins in C is pretty straight forward if you're comfortable in the language. The plugin API is written in C (for compatibility), so if you're comfortable in C, you should be right at home. ## Getting started @@ -25,7 +25,7 @@ cargo build This ensures all libraries and bindings are compiled before you get started. !!! note - If you're writing plugins for release (`-02`), build the crate using the release profile by passing `--release` flag to Cargo. + If you're writing plugins for release (`-02`), build the crate using the release profile by passing `--release` flag to Cargo. The shared library will be placed in `target/(debug|release)` and you can link to it like so: @@ -36,7 +36,7 @@ gcc plugin.c -lpgdog_routing -lshared -o plugin.so ### Memory safety -All structures passed to plugins are owned by pgDog runtime, so make sure not to `free` any pointers. All structures passed back to pgDog will be freed automatically by pgDog, so you don't need to worry about leaks. +All structures passed to plugins are owned by PgDog runtime, so make sure not to `free` any pointers. All structures passed back to PgDog will be freed automatically by PgDog, so you don't need to worry about leaks. If you allocate any memory during routine execution, make sure to free it before you return from the plugin API call. diff --git a/docs/docs/features/plugins/index.md b/docs/docs/features/plugins/index.md index ed2afe69..fcb042e5 100644 --- a/docs/docs/features/plugins/index.md +++ b/docs/docs/features/plugins/index.md @@ -1,19 +1,19 @@ # Plugins overview -One of features that make pgDog particularly powerful is its plugin system. Users of pgDog can write plugins +One of features that make PgDog particularly powerful is its plugin system. Users of PgDog can write plugins in any language and inject them inside the query router to direct query traffic, to rewrite queries, or to block them entirely and return custom results. ## API -pgDog plugins are shared libraries loaded at application startup. They can be written in any programming language, as long +PgDog plugins are shared libraries loaded at application startup. They can be written in any programming language, as long as that language can be compiled to a shared library, and can expose a predefined set of C ABI-compatible functions. ### Functions #### `pgdog_init` -This function is executed once when pgDog loads the plugin, at application startup. It allows to initialize any +This function is executed once when PgDog loads the plugin, at application startup. It allows to initialize any kind of internal plugin state. Execution of this function is synchronized, so it's safe to execute any thread-unsafe functions or initialize synchronization primitives, like mutexes. @@ -55,11 +55,11 @@ This function has the following signature: ##### Data structures This function expects an input of type `Input` and must return a struct of type `Output`. The input contains -the query pgDog received and the current database configuration, e.g. number of shards, replicas, and if there +the query PgDog received and the current database configuration, e.g. number of shards, replicas, and if there is a primary database that can serve writes. The output structure contains the routing decision (e.g. query should go to a replica) and any additional information that the plugin wants to communicate, which depends on the routing decision. For example, -if the plugin wants pgDog to intercept this query and return a custom result, rows of that result will be +if the plugin wants PgDog to intercept this query and return a custom result, rows of that result will be included in the output. diff --git a/docs/docs/features/plugins/rust.md b/docs/docs/features/plugins/rust.md index c91c30a0..06036436 100644 --- a/docs/docs/features/plugins/rust.md +++ b/docs/docs/features/plugins/rust.md @@ -1,18 +1,18 @@ # Plugins in Rust -Writing pgDog plugins in Rust has first class support built into the [`pgdog-plugin`](https://github.com/levkk/pgdog/tree/main/pgdog-plugin) crate. The crate acts -as a bridge between plugins and pgDog internals, and provides safe methods for constructing C-compatible structs. +Writing PgDog plugins in Rust has first class support built into the [`pgdog-plugin`](https://github.com/levkk/pgdog/tree/main/pgdog-plugin) crate. The crate acts +as a bridge between plugins and PgDog internals, and provides safe methods for constructing C-compatible structs. ## How it works -For plugins to be truly dynamic, they have to be compiled into shared libraries (`.so` on Linux, `.dylib` on Mac). This way you can load arbitrary plugins into pgDog at runtime without having to recompile it. Since Rust doesn't have a stable [ABI](https://en.wikipedia.org/wiki/Application_binary_interface), we have to use the only stable ABI available to all programming languages: C. +For plugins to be truly dynamic, they have to be compiled into shared libraries (`.so` on Linux, `.dylib` on Mac). This way you can load arbitrary plugins into PgDog at runtime without having to recompile it. Since Rust doesn't have a stable [ABI](https://en.wikipedia.org/wiki/Application_binary_interface), we have to use the only stable ABI available to all programming languages: C. ### C ABI Rust has great bindings for using (and exposing) C-compatible functions. You can learn more about this by reading the [`std::ffi`](https://doc.rust-lang.org/stable/std/ffi/index.html) documentation and other great sources like The Embedded Rust Book[^1]. The [`pgdog-plugin`](https://github.com/levkk/pgdog/tree/main/pgdog-plugin) crate contains C [headers](https://github.com/levkk/pgdog/tree/main/pgdog-plugin/include) that define -types and functions pgDog expects its plugins to use, with Rust bindings generated with [bindgen](https://docs.rs/bindgen/latest/bindgen/). +types and functions PgDog expects its plugins to use, with Rust bindings generated with [bindgen](https://docs.rs/bindgen/latest/bindgen/). [^1]: [https://docs.rust-embedded.org/book/interoperability/rust-with-c.html](https://docs.rust-embedded.org/book/interoperability/rust-with-c.html) @@ -35,7 +35,7 @@ crate-type = ["rlib", "cdylib"] ### Add `pgdog-plugin` -To make building plugins easier, pgDog provides a crate that defines and implements the structs used by +To make building plugins easier, PgDog provides a crate that defines and implements the structs used by plugin functions. Before proceeding, add this crate to your dependencies: @@ -46,7 +46,7 @@ cargo add pgdog-plugin ### Implement the API -The [plugin API](../plugins/index.md) is pretty simple. For this tutorial, we'll implement the query routing function `pgdog_route_query`, which is called for the first query in every transaction pgDog receives. +The [plugin API](../plugins/index.md) is pretty simple. For this tutorial, we'll implement the query routing function `pgdog_route_query`, which is called for the first query in every transaction PgDog receives. This function has the following signature: @@ -59,18 +59,18 @@ pub extern "C" fn pgdog_route_query(input: Input) -> Output { } ``` -The [`Input`](https://docs.rs/pgdog-plugin/latest/pgdog_plugin/input/index.html) structure contains the query pgDog received and the current state of the pooler configuration, like +The [`Input`](https://docs.rs/pgdog-plugin/latest/pgdog_plugin/input/index.html) structure contains the query PgDog received and the current state of the pooler configuration, like the number of shards, the number of replicas and their addresses, and other information which the plugin can use -to determine where the query should go. +to determine where the query should go. The plugin is expected to return an [`Output`](https://docs.rs/pgdog-plugin/latest/pgdog_plugin/output/index.html) structure which contains its routing decision and any additional data -the plugin wants pgDog to use, like an error it wants pgDog to return to the client instead, for example. +the plugin wants PgDog to use, like an error it wants PgDog to return to the client instead, for example. Both structures have Rust implementations which can help us avoid having to write C-like initialization code. ### Parse the input -You can get the query pgDog received from the input structure like so: +You can get the query PgDog received from the input structure like so: ```rust if let Some(query) = input.query() { @@ -90,8 +90,8 @@ let route = if query.starts_with("SELECT") { } ``` -Both `read_any` and `write_any` are typically used in a single shard configuration and tell pgDog -that the shard number is not important. pgDog will send the query to the first shard in the configuration. +Both `read_any` and `write_any` are typically used in a single shard configuration and tell PgDog +that the shard number is not important. PgDog will send the query to the first shard in the configuration. ### Return the output @@ -101,13 +101,13 @@ The `Output` structure contains the routing decision and any additional metadata return Output::forward(route) ``` -Not all plugins have to make a routing decision. For example, if your plugin just wants to count how many queries of a certain type your database receives but doesn't care about routing, you can tell pgDog to skip your plugin's routing decision: +Not all plugins have to make a routing decision. For example, if your plugin just wants to count how many queries of a certain type your database receives but doesn't care about routing, you can tell PgDog to skip your plugin's routing decision: ```rust return Output::skip() ``` -pgDog will ignore this output and pass the query to the next plugin in the chain. +PgDog will ignore this output and pass the query to the next plugin in the chain. ### Parsing query parameters @@ -123,7 +123,7 @@ SELECT * FROM users WHERE id = $1 If your plugin is sharding requests based on a hash (or some other function) of the `"users"."id"` column, you need to see the value of `$1` before your plugin can make a decision. -pgDog supports parsing the extended protocol and provides the full query text and parameters to its plugins. You can access a specific parameter by calling `Query::parameter`: +PgDog supports parsing the extended protocol and provides the full query text and parameters to its plugins. You can access a specific parameter by calling `Query::parameter`: ```rust if let Some(id) = query.parameter(0) { @@ -133,7 +133,7 @@ if let Some(id) = query.parameter(0) { !!! note PostgreSQL uses a lot of 1-based indexing, e.g. parameters and arrays - start at 1. pgDog is more "rusty" and uses 0-based indexing. To access the first + start at 1. PgDog is more "rusty" and uses 0-based indexing. To access the first parameter in a query, index it by `0`, not `1`. Parameters are encoded using PostgreSQL wire protocol, so they can be either UTF-8 text or binary. If they are text, @@ -165,7 +165,7 @@ parsing vector-encoded fields. ## SQL parsers -Parsing SQL manually can be error-prone, and there are multiple great SQL parsers you can pick off the shelf. The [pgdog-routing](https://github.com/levkk/pgdog/tree/main/plugins/pgdog-routing) plugin which ships with pgDog uses `pg_query.rs`, which in turn uses the internal PostgreSQL query +Parsing SQL manually can be error-prone, and there are multiple great SQL parsers you can pick off the shelf. The [pgdog-routing](https://github.com/levkk/pgdog/tree/main/plugins/pgdog-routing) plugin which ships with PgDog uses `pg_query.rs`, which in turn uses the internal PostgreSQL query parser. This ensures all valid PostgreSQL queries are recognized and parsed correctly. Other SQL parsers in the Rust community include [sqlparser](https://docs.rs/sqlparser/latest/sqlparser/) which @@ -173,7 +173,7 @@ can parse many dialects, including other databases like MySQL, if you wanted to ## Handling errors -Since plugins use the C ABI, pgDog is not able to catch panics inside plugins. Therefore, if a plugin panics, this will cause an abort and shutdown the pooler. +Since plugins use the C ABI, PgDog is not able to catch panics inside plugins. Therefore, if a plugin panics, this will cause an abort and shutdown the pooler. The vast majority of the Rust standard library and crates avoid panicking and return errors instead. Plugin code must check for error conditions and handle them internally. Notably, don't use `unwrap()` on `Option` or `Result` types and handle each case instead. @@ -185,8 +185,7 @@ The vast majority of the Rust standard library and crates avoid panicking and re ## Learn more -pgDog plugins are in their infancy and many more features will be added over time. For now, the API +PgDog plugins are in their infancy and many more features will be added over time. For now, the API is pretty bare bones but can already do useful things. Our bundled plugin we use for routing is called [pgdog-routing](https://github.com/levkk/pgdog/tree/main/plugins/pgdog-routing) and it can be used as the basis for your plugin development. - diff --git a/docs/docs/features/session-mode.md b/docs/docs/features/session-mode.md index 52d2a14c..36bd9a3b 100644 --- a/docs/docs/features/session-mode.md +++ b/docs/docs/features/session-mode.md @@ -1,6 +1,6 @@ # Session mode -In session mode, pgDog allocates one PostgreSQL server connection per client. This ensures that all PostgreSQL features work as expected, including persistent session variables, settings, and +In session mode, PgDog allocates one PostgreSQL server connection per client. This ensures that all PostgreSQL features work as expected, including persistent session variables, settings, and process-based features like `LISTEN`/`NOTIFY`. Some batch-based tasks, like ingesting large amounts of data, perform better in session mode. ## Enable session mode @@ -27,16 +27,16 @@ is controlled by the `default_pool_size` (and `pool_size`) settings. For example only 15 clients will be able to connect and use the database at any given moment. !!! note - In session mode, when the connection pool reaches full capacity, a client has to disconnect before another one can connect to pgDog. + In session mode, when the connection pool reaches full capacity, a client has to disconnect before another one can connect to PgDog. ### Benefits of session mode -Using pgDog in session mode is still an improvement over connecting to PostgreSQL directly. Since the proxy maintains a pool of open server connections, +Using PgDog in session mode is still an improvement over connecting to PostgreSQL directly. Since the proxy maintains a pool of open server connections, when a client disconnects, the PostgreSQL server connection remains intact and can be reused by another client. #### Lazy connections -Until a client issues their first query, pgDog doesn't attach it to a server connection. This allows one set of clients to connect before the previous set disconnects, +Until a client issues their first query, PgDog doesn't attach it to a server connection. This allows one set of clients to connect before the previous set disconnects, which is common when using zero-downtime deployment strategies like blue/green[^1]. [^1]: [https://docs.aws.amazon.com/whitepapers/latest/overview-deployment-options/bluegreen-deployments.html](https://docs.aws.amazon.com/whitepapers/latest/overview-deployment-options/bluegreen-deployments.html) diff --git a/docs/docs/features/sharding/cross-shard.md b/docs/docs/features/sharding/cross-shard.md index a6f918c3..dec018bf 100644 --- a/docs/docs/features/sharding/cross-shard.md +++ b/docs/docs/features/sharding/cross-shard.md @@ -1,6 +1,6 @@ # Cross-shard queries -If a client can't or chooses not to provide a sharding key, pgDog can route the query to all shards and combine the results transparently. To the client, this feels like the query executed against a single database. +If a client can't or chooses not to provide a sharding key, PgDog can route the query to all shards and combine the results transparently. To the client, this feels like the query executed against a single database. <center style="margin-top: 2rem;"> <img src="/images/cross-shard.png" width="70%" alt="Cross-shard queries" /> @@ -9,14 +9,14 @@ If a client can't or chooses not to provide a sharding key, pgDog can route the ## Architecture -Since pgDog speaks the Postgres protocol, it can connect to multiple database servers and collect `DataRow`[^1] messages as they are being sent by each server. Once all servers finish -executing the query, pgDog processes the result and sends it to the client as if all messages came from one server. +Since PgDog speaks the Postgres protocol, it can connect to multiple database servers and collect `DataRow`[^1] messages as they are being sent by each server. Once all servers finish +executing the query, PgDog processes the result and sends it to the client as if all messages came from one server. While this works for simple queries, others that involve sorting or aggregation are more complex and require special handling. ## Sorting -If the client requests results to be ordered by one or more columns, pgDog can interpret this request and perform the sorting once it receives all data messages from Postgres. For queries that span multiple shards, this feature allows to retrieve results in the correct order. For example: +If the client requests results to be ordered by one or more columns, PgDog can interpret this request and perform the sorting once it receives all data messages from Postgres. For queries that span multiple shards, this feature allows to retrieve results in the correct order. For example: ```postgresql SELECT * @@ -25,10 +25,10 @@ WHERE admin IS true ORDER BY id DESC; ``` -This query has no sharding key, so pgDog will send it to all shards in parallel. Once all shards receive the query, they will filter data from their respective `"users"` table and send +This query has no sharding key, so PgDog will send it to all shards in parallel. Once all shards receive the query, they will filter data from their respective `"users"` table and send the results ordered by the `"id"` column. -pgDog will receive rows from all shards at the same time, however Postgres is not aware of other shards in the system so the overall sorting order will be wrong. pgDog will collect all rows, and sort them by the `"id"` column before sending the results over to the client. +PgDog will receive rows from all shards at the same time, however Postgres is not aware of other shards in the system so the overall sorting order will be wrong. PgDog will collect all rows, and sort them by the `"id"` column before sending the results over to the client. Two kinds of sorting is supported: @@ -37,12 +37,12 @@ Two kinds of sorting is supported: ### Order by column name -pgDog can extract the column name(s) from the `ORDER BY` clause of a query and match them +PgDog can extract the column name(s) from the `ORDER BY` clause of a query and match them to values in `DataRow`[^1] messages based on their position in the `RowDescription`[^1] message received as the query starts executing on the shards. For example, if the query specifies `ORDER BY id ASC, email DESC`, both `"id"` and `"email"` columns will be present in the `RowDescription` message along with their data types and locations in `DataRow`[^1] messages. -Once the messages are buffered in pgDog, it will sort them using the data extracted from messages and return the sorted result to the client. +Once the messages are buffered in PgDog, it will sort them using the data extracted from messages and return the sorted result to the client. #### Example diff --git a/docs/docs/features/sharding/index.md b/docs/docs/features/sharding/index.md index 1478ebbb..22c8c714 100644 --- a/docs/docs/features/sharding/index.md +++ b/docs/docs/features/sharding/index.md @@ -3,7 +3,7 @@ !!! note This feature is under active development. It's not ready production use. -Sharding PostgreSQL databases involves splitting the database between multiple machines and routing queries to the right machines using a sharding function. Like its [predecessor](https://github.com/levkk/pgcat), pgDog supports sharded PostgreSQL deployments and can route queries to the correct shards automatically, implemented as a [plugin](../plugins/index.md). +Sharding PostgreSQL databases involves splitting the database between multiple machines and routing queries to the right machines using a sharding function. Like its [predecessor](https://github.com/levkk/pgcat), PgDog supports sharded PostgreSQL deployments and can route queries to the correct shards automatically, implemented as a [plugin](../plugins/index.md). <center style="margin-top: 2rem;"> <img src="/images/sharding.png" width="70%" alt="Sharding" /> @@ -14,7 +14,7 @@ Sharding PostgreSQL databases involves splitting the database between multiple m There are two ways for database clients to query sharded databases: by connecting to specific shard, or by querying all shards and aggregating the results. The former is commonly used in OLTP (transactional) systems, e.g. real time applications, and the latter is more commonly used in OLAP (analytical) databases, e.g. batch reports generation. -pgDog has good support for single shard queries, and adding support for aggregates over time[^1]. +PgDog has good support for single shard queries, and adding support for aggregates over time[^1]. [^1]: Aggregation can get pretty complex and sometimes requires query rewriting. Examples can be found in the PostgreSQL's [postgres_fdw](https://www.postgresql.org/docs/current/postgres-fdw.html) extension. @@ -24,7 +24,7 @@ The [`pgdog-routing`](https://github.com/levkk/pgdog/tree/main/plugins/pgdog-rou ### Multi-shard queries -When the sharding key isn't available or impossible to extract from a query, pgDog can route the query to all shards and return results combined in a [single response](cross-shard.md). Clients using this feature are not aware they are communicating with a sharded database and can treat pgDog connections like normal. +When the sharding key isn't available or impossible to extract from a query, PgDog can route the query to all shards and return results combined in a [single response](cross-shard.md). Clients using this feature are not aware they are communicating with a sharded database and can treat PgDog connections like normal. ## Learn more diff --git a/docs/docs/features/sharding/manual-routing.md b/docs/docs/features/sharding/manual-routing.md index e51ad159..7e739a06 100644 --- a/docs/docs/features/sharding/manual-routing.md +++ b/docs/docs/features/sharding/manual-routing.md @@ -1,7 +1,7 @@ # Manual routing In cases where the sharding key is not obvious or can't be extracted from the query, -pgDog supports extracting it from a query comment. For example: +PgDog supports extracting it from a query comment. For example: ```postgresql /* pgdog_shard: 1 */ SELECT * FROM users WHERE email = $1 @@ -31,7 +31,7 @@ If you don't know the shard number but have a sharding key, e.g., the value of a /* pgdog_sharding_key: <value> */ ``` -pgDog will extract this value from the query and apply a [sharding function](sharding-functions.md) to find out the actual shard number. +PgDog will extract this value from the query and apply a [sharding function](sharding-functions.md) to find out the actual shard number. ## Usage in frameworks diff --git a/docs/docs/features/transaction-mode.md b/docs/docs/features/transaction-mode.md index 29151631..3a0edc42 100644 --- a/docs/docs/features/transaction-mode.md +++ b/docs/docs/features/transaction-mode.md @@ -1,6 +1,6 @@ # Transaction mode -In transaction mode, pgDog is able to multiplex client transactions with several PostgreSQL backend servers. This +In transaction mode, PgDog is able to multiplex client transactions with several PostgreSQL backend servers. This allows the pooler to serve thousands of clients using only dozens of actual server connections. This feature is essential for at-scale PostgreSQL deployments since Postgres is not able to maintain more than a few thousand concurrently open connections. @@ -33,9 +33,9 @@ and user level: !!! note This feature is a work in progress. -Since clients in transaction mode reuse PostgreSQL server connections, it's possible for session-level variables and state to leak between clients. pgDog keeps track of connection state modifications and can automatically clean up server connections after a transaction. While this helps prevent session variables leakage between clients, this does have a small performance overhead. +Since clients in transaction mode reuse PostgreSQL server connections, it's possible for session-level variables and state to leak between clients. PgDog keeps track of connection state modifications and can automatically clean up server connections after a transaction. While this helps prevent session variables leakage between clients, this does have a small performance overhead. -To avoid this, clients using pgDog in transaction mode should avoid the usage of `SET` statements and use `SET LOCAL` inside an explicit transaction instead: +To avoid this, clients using PgDog in transaction mode should avoid the usage of `SET` statements and use `SET LOCAL` inside an explicit transaction instead: ```postgresql BEGIN; diff --git a/docs/docs/index.md b/docs/docs/index.md index 470a0d4a..b8b04eca 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -1,28 +1,28 @@ -# pgDog +# PgDog -[pgDog](https://github.com/levkk/pgdog) is a PostgreSQL query router, pooler, proxy and load balancer written in Rust. Spiritual successor to -[pgcat](https://github.com/levkk/pgcat), pgDog comes with a lot of similar features, better performance, -and introduces new features like plugins. +[PgDog](https://github.com/levkk/pgdog) is a PostgreSQL query router, pooler, proxy and load balancer written in Rust. Spiritual successor to +[pgcat](https://github.com/levkk/pgcat), PgDog comes with a lot of similar features, better performance, +and introduces new features like plugins and cross-shard queries. -PostgreSQL deployments of any size can be proxied by pgDog, ranging from a single database to hundreds of primaries and replicas in a sharded configuration. +PostgreSQL deployments of any size can be proxied by PgDog, ranging from a single database to hundreds of primaries and replicas in a sharded configuration. ## Installation -pgDog is easily compiled from source. Before proceeding, make sure you have the latest version of the Rust +PgDog is easily compiled from source. Before proceeding, make sure you have the latest version of the Rust compiler, available from [rust-lang.org](https://rust-lang.org). ### Checkout the code -pgDog source code can be downloaded from [GitHub](https://github.com/levkk/pgdog): +PgDog source code can be downloaded from [GitHub](https://github.com/levkk/pgdog): ```bash git clone https://github.com/levkk/pgdog && \ cd pgdog ``` -### Compile pgDog +### Compile PgDog -pgDog should be compiled in release mode to make sure you get all performance benefits. You can do this with Cargo: +PgDog should be compiled in release mode to make sure you get all performance benefits. You can do this with Cargo: ```bash cargo build --release @@ -30,7 +30,7 @@ cargo build --release ### Configuration -pgDog is [configured](configuration/index.md) via two files: +PgDog is [configured](configuration/index.md) via two files: * [`pgdog.toml`](configuration/index.md) which contains general pooler settings and PostgreSQL server information * [`users.toml`](configuration/users.toml/users.md) which contains passwords for users allowed to connect to the pooler @@ -38,12 +38,12 @@ pgDog is [configured](configuration/index.md) via two files: The passwords are stored in a separate file to simplify deployments in environments where secrets can be safely encrypted, like Kubernetes or AWS EC2. -Both files can to be placed in the current working directory (CWD) for pgDog to detect them. Alternatively, -you can pass the `--config` and `--secrets` arguments with their locations when starting pgDog. +Both files can to be placed in the current working directory (CWD) for PgDog to detect them. Alternatively, +you can pass the `--config` and `--secrets` arguments with their locations when starting PgDog. #### Example `pgdog.toml` -Most pgDog configuration options have sensible defaults. This allows a basic primary-only configuration to be pretty short: +Most PgDog configuration options have sensible defaults. This allows a basic primary-only configuration to be pretty short: ```toml [general] @@ -58,7 +58,7 @@ host = "127.0.0.1" #### Example `users.toml` This configuration file contains a mapping between databases, users and passwords. Users not specified in this file -won't be able to connect to pgDog: +won't be able to connect to PgDog: ```toml [[users]] @@ -79,11 +79,11 @@ Starting the pooler can be done by running the binary in `target/release` folder === "Output" ``` - INFO 🐕 pgDog 0.1.0 + INFO 🐕 PgDog 0.1.0 INFO loaded pgdog.toml INFO loaded users.toml INFO loaded "pgdog_routing" plugin [1.0461ms] - INFO 🐕 pgDog listening on 0.0.0.0:6432 + INFO 🐕 PgDog listening on 0.0.0.0:6432 INFO new server connection [127.0.0.1:5432] ``` diff --git a/pgdog-plugin/README.md b/pgdog-plugin/README.md index fbdf298f..3c5327de 100644 --- a/pgdog-plugin/README.md +++ b/pgdog-plugin/README.md @@ -1,15 +1,15 @@ -# pgDog plugins +# PgDog plugins [![Documentation](https://img.shields.io/badge/documentation-blue?style=flat)](https://pgdog.dev) [![Latest crate](https://img.shields.io/crates/v/pgdog-plugin.svg)](https://crates.io/crates/pgdog-plugin) [![Reference docs](https://img.shields.io/docsrs/pgdog-plugin)](https://docs.rs/pgdog-plugin/) -pgDog plugin system is based around shared libraries loaded at runtime. +PgDog plugin system is based around shared libraries loaded at runtime. These libraries can be written in any language as long as they are compiled to `.so` (or `.dylib` on Mac), and can expose predefined C ABI functions. -This crate implements the bridge between the C ABI and pgDog, defines common C types and interface to use, -and exposes internal pgDog configuration. +This crate implements the bridge between the C ABI and PgDog, defines common C types and interface to use, +and exposes internal PgDog configuration. This crate is a C (and Rust) library that should be linked at compile time against your plugins. diff --git a/pgdog.toml b/pgdog.toml index 1aee8b5f..c93e7851 100644 --- a/pgdog.toml +++ b/pgdog.toml @@ -34,7 +34,7 @@ shard = 1 # -# Write access to this table will be automatically +# Read/write access to theses tables will be automatically # sharded. # [[sharded_tables]] @@ -42,6 +42,11 @@ database = "pgdog_sharded" table = "sharded" column = "id" +[[sharded_tables]] +database = "pgdog_sharded" +table = "users" +column = "id" + # # ActiveRecord sends these queries # at startup to figure out the schema. diff --git a/pgdog/src/frontend/client.rs b/pgdog/src/frontend/client.rs index 1f9456a1..695bf93d 100644 --- a/pgdog/src/frontend/client.rs +++ b/pgdog/src/frontend/client.rs @@ -183,7 +183,13 @@ impl Client { debug!("{} [{}]", query, self.addr); } - let command = backend.cluster().ok().map(|cluster| router.query(&buffer, cluster)).transpose()?; + let command = match backend.cluster().ok().map(|cluster| router.query(&buffer, cluster)).transpose() { + Ok(command) => command, + Err(err) => { + self.stream.error(ErrorResponse::syntax(err.to_string().as_str())).await?; + continue; + } + }; self.streaming = matches!(command, Some(Command::StartReplication)); diff --git a/pgdog/src/frontend/router/parser/insert.rs b/pgdog/src/frontend/router/parser/insert.rs new file mode 100644 index 00000000..837681d2 --- /dev/null +++ b/pgdog/src/frontend/router/parser/insert.rs @@ -0,0 +1 @@ +//! Handle INSERT statements. diff --git a/pgdog/src/frontend/router/parser/mod.rs b/pgdog/src/frontend/router/parser/mod.rs index 669f7b9e..651422f1 100644 --- a/pgdog/src/frontend/router/parser/mod.rs +++ b/pgdog/src/frontend/router/parser/mod.rs @@ -4,6 +4,7 @@ pub mod comment; pub mod copy; pub mod csv_buffer; pub mod error; +pub mod insert; pub mod order_by; pub mod query; pub mod route; diff --git a/pgdog/tests/users.csv b/pgdog/tests/users.csv new file mode 100644 index 00000000..4bdf0867 --- /dev/null +++ b/pgdog/tests/users.csv @@ -0,0 +1,15 @@ +id,email +1,admin@pgdog.dev +2,user@pgdog.dev +3,yc@pgdog.dev +4,apple@pgdog.dev +5,google@pgdog.dev +6,instacart@pgdog.dev +7,doordash@pgdog.dev +8,uber@pgdog.dev +9,airbnb@pgdog.dev +10,onesignal@pgdog.dev +11,bananarepublic@pgdog.dev +12,redhat@pgdog.dev +13,nvidia@pgdog.dev +14,amd@pgdog.dev diff --git a/plugins/README.md b/plugins/README.md index cddd4c0b..c8d86ca3 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -1,12 +1,12 @@ -# pgDog plugins +# PgDog plugins -This directory contains (now and in the future) plugins that ship with pgDog and are built by original author(s) +This directory contains (now and in the future) plugins that ship with PgDog and are built by original author(s) or the community. You can use these as-is or modify them to your needs. ## Plugins ### `pgdog-routing` -The only plugin in here right now and the catch-all for routing traffic through pgDog. This plugin uses `pg_query.rs` (Rust bindings to `pg_query`) +The only plugin in here right now and the catch-all for routing traffic through PgDog. This plugin uses `pg_query.rs` (Rust bindings to `pg_query`) to parse queries using the PostgreSQL parser, and splits traffic between primary and replicas. This allows users of this plugin to deploy -primaries and replicas in one pgDog configuration. +primaries and replicas in one PgDog configuration. diff --git a/users.toml b/users.toml index 1be87b0e..5674f207 100644 --- a/users.toml +++ b/users.toml @@ -9,8 +9,8 @@ name = "pgdog" database = "pgdog" password = "pgdog" -# replication_mode = true -# replication_sharding = "pgdog_sharded" +replication_mode = true +replication_sharding = "pgdog_sharded" [[users]] name = "pgdog_replication" [parent: 9e74470fbc2b]