当前位置:首页 > 问答 > 正文

PostgreSQL主从复制里头逻辑复制到底怎么搞,和传统方式有啥区别和注意点

PostgreSQL的主从复制主要有两种大的路子:一种是物理复制,另一种就是你问的逻辑复制,可以把物理复制理解成给数据库做“整盘克隆”,而逻辑复制更像是“选择性抄写”。

传统方式:物理复制(流复制)

物理复制是PostgreSQL最核心、最常用、也最成熟的高可用和读写分离方案,它的原理其实不复杂(引自PostgreSQL官方文档关于流复制的描述): 主库(Master)在运行时,会持续产生一种叫WAL(预写式日志)的文件,你可以把这个WAL日志想象成数据库所有底层操作的“录像带”,里面记录的不是一条条SQL语句,而是数据块发生了什么变化(在表A的第5个数据页的第100个字节位置写入了数值100”),从库(Standby)会不断地从主库拉取这些WAL日志记录,然后在自己的数据库上,严格按照相同的顺序“播放”这些变化,因为是从底层数据块层面进行复制,所以主从库的数据在物理层面上是完全一样的,可以看作是字节级别的镜像。

物理复制的特点和注意点:

  1. 高度一致性:主从库的数据块级一致,保证了数据的强一致性,从库是整个数据库的完整副本,不能只复制一部分表。
  2. 简单可靠:部署和运维相对简单,是PostgreSQL的“标准配置”,社区支持最好,非常稳定。
  3. 版本要求:主从库的PostgreSQL大版本必须完全一致,你不能用PostgreSQL 15的主库去流复制到一个PostgreSQL 14的从库。
  4. 延迟敏感:如果网络不稳定或者从库因为查询压力大导致“播放”WAL的速度跟不上主库“录像”的速度,就会产生复制延迟,高延迟下,从库读到的数据可能是过时的。
  5. 只读从库:物理从库默认是只读的,不能接受任何写入操作,主要用于分担主库的读压力或做高可用备份。

逻辑复制到底怎么搞?

逻辑复制是在PostgreSQL 10版本之后才正式内置的核心功能,它走了另一条路(原理基于PostgreSQL官方文档对逻辑复制的说明): 逻辑复制不是复制底层数据块的变化,而是复制逻辑层面的数据变更,它基于一种叫“发布-订阅”的模型,在主库端,你需要为一个或一组表创建一个“发布”(Publication),就像发布一个公告说“我这几个表的变化情况,有兴趣的可以来订阅”,在从库端,你创建一个“订阅”(Subscription),指向主库的发布,相当于“我订阅了主库那几个表的变化消息”。

PostgreSQL主从复制里头逻辑复制到底怎么搞,和传统方式有啥区别和注意点

变化消息是什么?是SQL语句吗?不完全是,逻辑复制依赖的是另一种日志,叫逻辑解码,它会把WAL日志中关于已提交事务的底层变更,翻译成一种逻辑化的、易于理解的数据格式(“在users表插入了一行,这行数据的id是1,name是‘张三’”),从库的订阅进程会接收到这些逻辑变化记录,再在从库端转换成相应的SQL语句(如INSERT INTO users (id, name) VALUES (1, ‘张三’);)执行。

逻辑复制的具体操作步骤(简化版):

  1. 配置主库

    PostgreSQL主从复制里头逻辑复制到底怎么搞,和传统方式有啥区别和注意点

    • 修改postgresql.conf,确保wal_level设置为logical(这很关键,物理复制用replica就够了,但逻辑复制必须用logical)。
    • 配置pg_hba.conf,允许从库服务器连接主库的复制账户。
    • 创建一个有复制权限的专用用户。
    • 在需要复制的表上创建发布:CREATE PUBLICATION my_publication FOR TABLE table1, table2;
  2. 配置从库

    • 从库本身可以是一个独立的、有自己数据库结构的PostgreSQL实例。
    • 创建与主库结构一致的表(表名、列名、数据类型必须相同,约束、索引可以不同)。
    • 创建订阅:CREATE SUBSCRIPTION my_subscription CONNECTION 'host=主库IP user=复制用户' PUBLICATION my_publication;
  3. 监控:创建订阅后,复制会自动开始,你可以通过系统视图如pg_stat_subscription来监控复制的状态和延迟。

逻辑复制和物理复质的核心区别与注意点:

  1. 复制粒度:这是最根本的区别,物理复制是“全库克隆”,而逻辑复制是“表级别筛选复制”,你可以选择只复制一部分业务核心表到从库,非常灵活。
  2. 版本和平台灵活性:逻辑复制对版本的要求放宽了,主从库的PostgreSQL大版本可以不同(例如15主库向14从库复制),只要它们都支持逻辑复制功能即可,理论上,甚至可以在不同操作系统平台之间进行逻辑复制。
  3. 从库的灵活性:逻辑从库不是只读的!你可以在从库上为那些没有被订阅的表创建额外的表,并执行读写操作,这使得逻辑复制不仅可以用于读写分离,还可以用于将数据聚合到中央数据库、或在从库上做一些复杂的计算和查询而不影响主库,但务必注意,要避免修改那些已被订阅的表的数据,否则可能导致复制冲突。
  4. 数据一致性:逻辑复制是最终一致性,而非物理复制的强一致性,因为它是事务级别的复制,可能存在极短暂的延迟,导致主从数据瞬间不一致。
  5. 对象支持范围:逻辑复制并非支持所有数据库对象,默认主要支持普通表的INSERT, UPDATE, DELETE操作(TRUNCATE需要额外配置),像序列(SEQUENCE)、大对象(LOB)、DDL操作(如ALTER TABLE)等,默认是不会通过逻辑复制同步的,这是逻辑复制一个非常重要的限制,需要额外的手动处理。
  6. 初始数据同步:创建订阅时,默认不会自动将主库的现有数据拷贝到从库,你需要先用pg_dump之类的工具手动做一次基础数据同步,或者使用订阅的COPY DATA选项(但可能不如手动控制可靠)。
  7. 性能和冲突:逻辑复制需要解析WAL和重新应用SQL,通常其开销会比物理复制稍大一些,延迟也可能更高,因为从库可写,更容易发生复制冲突(比如从库修改了一条记录,同时主库也修改了同一条记录,从库在应用主库变更时就会失败),需要人工介入解决。

总结一下该选哪个:

  • 如果你需要整个数据库的高可用、灾备、完整的读写分离,并且希望方案最稳定、最简单,首选物理复制
  • 如果你需要选择性复制部分表、需要在从库上进行自定义写入、或者需要在不同大版本或平台的PostgreSQL之间同步数据,那么逻辑复制是你的不二之选。

简单说,物理复制是建房子的地基,保证整体稳固;逻辑复制是房子里的智能家居系统,让你可以精细化控制各个房间,两者都是PostgreSQL强大的数据同步工具,根据你的具体场景来选用,甚至在某些复杂场景下,它们可以结合使用。