精通PostgreSQL复制:类型与设置详解
在高级开源关系型数据库领域,PostgreSQL以其健壮性、可扩展性和强大功能脱颖而出。其中,数据冗余和高可用性对于关键任务应用程序至关重要。PostgreSQL复制是一种机制,它通过将数据从一个PostgreSQL服务器(主服务器)复制到一个或多个其他PostgreSQL服务器(副本或备用服务器),从而帮助您实现这些目标。
本文将深入探讨PostgreSQL复制的核心概念,探索可用的不同类型,并提供有关如何设置它们的实用指导。理解这些机制对于确保您的数据始终可访问、防止硬件故障以及处理增加的读取负载至关重要。我们将涵盖流复制和逻辑复制,解释它们的用例、优势和配置步骤。
为什么PostgreSQL复制很重要
在深入了解“如何做”之前,理解“为什么做”至关重要。数据丢失或长时间停机可能对企业造成严重后果。复制通过以下方式解决了这些问题:
- 高可用性 (HA): 如果主服务器发生故障,副本可以迅速提升为新的主服务器,从而最大程度地减少停机时间。
- 灾难恢复 (DR): 副本可以放置在不同的地理位置,保护您的数据免受特定站点的灾难影响。
- 读取可伸缩性: 将读取密集型工作负载分载到副本可以提高主服务器的性能,主服务器仍专注于写入操作。
- 数据保护: 复制作为一种持续备份,提供比传统周期性备份更即时的数据副本。
PostgreSQL提供了两种主要的复制方法:流复制和逻辑复制。尽管两者都能实现数据同步,但它们基于不同的原理运行,适用于不同的场景。
流复制(物理复制)
流复制是PostgreSQL中最常见、最基本的复制形式。它的工作原理是将预写日志(WAL)记录从主服务器发送到一个或多个副本。这些WAL记录代表了对数据库所做的每一个更改。然后,副本将这些WAL记录应用到它们自己的数据文件中,确保与主服务器保持一致。
流复制的类型:
-
同步复制: 在同步模式下,主服务器会等待至少一个(或指定数量)副本确认WAL记录已接收并写入其WAL缓冲区后,才会向客户端确认事务提交。这保证了已提交的事务至少存在于一个副本上,提供了最高级别的数据一致性。
- 优点: 保证同步副本上的已提交事务不会丢失数据。
- 缺点: 可能会引入事务提交延迟,因为主服务器必须等待副本的确认。
-
异步复制: 在异步模式下,主服务器将WAL记录发送到副本,但在提交事务之前不会等待确认。主服务器在本地写入WAL后立即向客户端确认提交。这提供了较低的延迟,但如果主服务器在WAL记录发送并应用到副本之前发生故障,则存在数据丢失的风险。
- 优点: 对事务提交延迟影响最小。
- 缺点: 如果主服务器发生故障且WAL记录尚未到达副本,则可能丢失数据。
设置流复制(异步示例)
设置流复制涉及配置主服务器和副本服务器。以下是一个简化指南:
1. 配置主服务器(postgresql.conf 和 pg_hba.conf)
在主服务器上,您需要启用WAL归档和复制连接。
-
postgresql.conf修改:```ini
wal_level = replica # or logical for logical replication
max_wal_senders = 5 # Number of concurrent replication connections
wal_keep_size = 512MB # Or wal_keep_segments for older versionsFor synchronous replication, add:
synchronous_standby_names = 'replica1,replica2'
Or for specific server name/priority:
synchronous_standby_names = '1 (replica1), 2 (replica2)'
archive_mode = on
archive_command = 'cp %p /path/to/wal_archive/%f'
`` *wal_level:对于流复制,必须至少为replica。 *max_wal_senders:指定可以同时连接的备用服务器数量。 *wal_keep_size:防止WAL文件在副本获取之前被删除(对于基本设置,这是archive_command的一个更简单的替代方案,但为了健壮性,建议使用归档)。 *archive_mode和archive_command`:对于时间点恢复(PITR)至关重要,并且如果副本落后太多或需要重建时必不可少。 -
pg_hba.conf修改:允许副本连接进行复制。将
replica_ip_address替换为副本的实际IP地址。```ini
TYPE DATABASE USER ADDRESS METHOD
host replication replication_user replica_ip_address/32 md5
```您还需要创建一个复制用户:
sql -- On the primary server: CREATE ROLE replication_user WITH REPLICATION LOGIN PASSWORD 'your_password';修改这些文件后,重新加载PostgreSQL配置:
```bash
pg_ctl reloadOr restart PostgreSQL if needed
```
2. 准备副本服务器
在启动副本之前,它必须有一个数据目录,该目录是主服务器数据目录在特定时间点的副本。最简单的方法是使用 pg_basebackup。
-
停止副本上的PostgreSQL(如果正在运行)。
-
执行基础备份:
```bash
Ensure PGDATA is empty or removed first
pg_basebackup -h primary_host_ip -p 5432 -U replication_user -D /var/lib/postgresql/data/ -Fp -Xs -P
`` *-h,-p,-U:指定主服务器的连接详细信息。 *-D:副本的数据目录。 *-Fp:格式为纯文本。 *-Xs:使用流式TSL/WAL流。等同于primary_conninfo设置中的WAL流。 *-P:显示进度。 * 系统将提示您输入replication_user` 的密码。
3. 配置副本服务器(PostgreSQL 12+使用 postgresql.conf,之前版本使用 recovery.conf 和 postgresql.conf)
-
postgresql.conf修改(适用于PG12+):```ini
hot_standby = on # Allows read-only queries on the replica
primary_conninfo = 'host=primary_host_ip port=5432 user=replication_user password=your_password'For synchronous replication, add:
primary_promote_delay = 10 # seconds
Or use a trigger file mechanism
`` *hot_standby:在备用服务器上启用只读查询。 *primary_conninfo`:到主服务器的连接字符串。 -
recovery.conf(适用于PostgreSQL 12之前的版本):在副本的数据目录中创建一个
recovery.conf文件,内容如下:```ini
standby_mode = 'on'
primary_conninfo = 'host=primary_host_ip port=5432 user=replication_user password=your_password'If using archive recovery instead of streaming, you'd specify restore_command
restore_command = 'cp /path/to/wal_archive/%f %p'
recovery_target_timeline = 'latest'
```
对于PG12+,
primary_conninfo和hot_standby直接在postgresql.conf中设置。
4. 启动副本服务器
启动副本上的PostgreSQL服务。它将连接到主服务器,接收WAL记录,并开始同步。您可以检查日志以进行确认。
提示: 为了实现健壮的HA,可以考虑使用Patroni或repmgr等工具,它们可以自动化故障转移和管理。
逻辑复制
逻辑复制是PostgreSQL 10中引入的一种更灵活、更精细的复制形式。它不是复制整个数据块或WAL记录,而是基于行级别的逻辑含义(例如INSERT、UPDATE、DELETE语句)来复制数据更改。这是通过将WAL记录解码成逻辑更改流来实现的。
主要特性和用例:
- 选择性复制: 您可以选择要复制哪些表,甚至哪些列。这对于在数据库之间选择性地移动数据非常有利。
- 跨版本复制: 逻辑复制可以在不同主要版本的PostgreSQL之间复制数据。
- 选择性模式更改: 您可以复制特定数据库或模式的更改,甚至只发布某些表。
- 数据转换: 虽然不是内置功能,但逻辑复制为更复杂的ETL(提取、转换、加载)过程提供了基础。
- 从主服务器复制到非完全克隆的副本: 目标数据库无需是源数据库的完整物理副本。
工作原理:
- 发布者(Publisher): 发生数据更改的源数据库(主服务器)。它需要
wal_level = logical。更改从WAL解码为逻辑流。 - 发布(Publication): 发布者上一个命名表集合,其更改将被复制。
- 订阅者(Subscriber): 接收更改的目标数据库(副本)。
- 订阅(Subscription): 订阅者上的一个连接,连接到发布者并应用来自特定发布的更改。
设置逻辑复制
1. 配置发布者(主服务器)
-
postgresql.conf修改:ini wal_level = logical max_replication_slots = 10 # For logical replication slots max_wal_senders = 10 # Should be at least max_replication_slots -
创建发布:
```sql
-- On the publisher database:
CREATE PUBLICATION my_publication FOR TABLE
table1,
table2
WITH (publish = 'insert,update,delete');-- Or for all tables:
-- CREATE PUBLICATION all_tables_pub FOR ALL TABLES;
```重新加载发布者上的配置。
2. 配置订阅者(副本服务器)
-
确保目标表存在: 订阅者数据库必须具有与发布者相同模式的目标表。您可以手动创建它们,或使用
pg_dump提取模式。 -
创建订阅:
sql -- On the subscriber database: CREATE SUBSCRIPTION my_subscription CONNECTION 'host=publisher_host_ip port=5432 user=replication_user password=your_password dbname=publisher_db' PUBLICATION my_publication;replication_user需要在发布者上拥有适当的权限。PostgreSQL将自动在发布者上创建一个复制槽,并开始应用更改。您可以使用订阅者上的
pg_stat_subscription监控订阅状态。
提示: 逻辑复制需要 logical decoding 扩展,该扩展通常是内置的。它比流复制更消耗资源,但提供了更大的灵活性。
选择正确的复制方法
- 流复制: 适用于高可用性和灾难恢复,您需要主数据库的精确字节级副本。它对于完整数据库复制设置更简单,并为只读副本提供了最佳的读取可伸缩性。
- 逻辑复制: 最适合选择性数据分发、迁移、跨版本升级,或者当您只需要复制数据子集时。它允许更复杂的场景,例如复制到不同的模式或执行数据转换。
结论
PostgreSQL复制是一个强大的功能,可以实现健壮的数据可用性、恢复和可伸缩性。无论您选择流复制的全面数据镜像,还是逻辑复制的灵活、选择性方法,理解它们的机制和配置都是维护健康且有弹性的PostgreSQL环境的关键。通过实施复制,您可以显著增强数据库的容错能力和性能。
始终彻底测试您的复制设置,特别是故障转移场景,并监控复制延迟以确保您的副本是最新的。持续学习和适应PostgreSQL不断发展的功能将进一步巩固您对这个不可或缺的数据库系统的掌握。