PostgreSQL主从复制-逻辑复制(pg数据库主从复制)
mhr18 2024-10-07 10:25 26 浏览 0 评论
1 物理复制及逻辑复制对比
前文做了PostgreSQL物理复制的部署,其有如下主要优点
- 物理层面完全一致,是主要的复制方式,其类似于Oracle的DG
- 延迟低,事务执行过程中产生REDO record,实时的在备库apply,事务结束时,备库立马能见到数据
- 物理复制的一致性、可靠性高,不必担心数据逻辑层面不一致
但是其又在实际使用的场景中存在一些无法满足的需求,例如:
- 无法满足指定库或部分表的复制需求
- 将多个数据库实例的数据汇聚到同一个目标库或将一个库的数据分发到多个不同的库
- 不同的版本之间的复制
- 不同库名之间的不同步
对于以上场景,物理复制是无法满足的,因此逻辑复制应运而生了。
逻辑复制的复制架构图如下:
图片来源于《PostgreSQL实战》
逻辑复制是基于逻辑解析,其核心原理是逻辑主库将Publication中表的WAL日志解析成一定格式并发送给逻辑备库,逻辑备库Subscription接收到解析后的WAL日志后进行重做,从而实现表数据同步。
2. 逻辑复制的部署
PS:以下的逻辑从库可以在新的机器上部署,如在原先的从库上修改,需停止原实例,并将recovery.conf文件删除或重命名(如修改为recovery.conf.done)
2.1 修改主库的postgresql.conf
可以基于原先的物理复制的配置文件进行修改,配置逻辑复制主要需调整如下参数
wal_level = logical
max_wal_senders = 10
max_replication_slots = 8
参数简要说明如下
- wal_level:设置成logical才支持逻辑复制
- max_wal_senders:由于每个订阅节点和流复制备库在主库上都会占用主库上一个WAL发送进程,因此此参数设置值需大于max_replication_slots参数值加上物理备库数量
- max_replication_slots:设置值需大于订阅节点的数量
2.2 修改逻辑从库的postgresql.conf
逻辑从库的postgresql.conf也可以在物理复制的基础上修改,与主库不同的是主要修改如下参数
wal_level = logical
max_replication_slots = 8
max_logical_replication_workers = 8
参数简要说明
- wal_level:设置成logical才支持逻辑复制,逻辑从库可以视情况设置
- max_replication_slots:设置数据库复制槽数量,应大于订阅节点的数量
- max_logical_replication_workers:设置逻辑复制进程数,应大于订阅节点的数量,并且给表同步预留一些进程数量,此参数默认值为4
2.3 创建逻辑复制账号
postgres=# CREATE USER logical_repl REPLICATION LOGIN CONNECTION LIMIT 8 ENCRYPTED PASSWORD 'logical_repl';
CREATE ROLE
逻辑复制用户需要REPLICATION权限即可,可以不需要SUPERUSER权限,之后需要在发布节点上将需要同步的表赋权给logical_repl用户,使logical_repl账号具有对这些表的读权限。
2.4 在逻辑主库上创建库及表
/** 创建用于逻辑复制的主库 */
[postgres@PG32 data]$ createdb sourcedb
[postgres@PG32 data]$ psql -d sourcedb
psql (11.4)
Type "help" for help.
sourcedb=# create table logical_tb1(id int primary key,name varchar(20));
2.5 逻辑从库上创建库及表
/** 在逻辑从库上创建不同的库 */
[postgres@PG33 data]$ createdb desdb
[postgres@PG33 data]$ psql -d desdb
psql (11.4)
Type "help" for help.
desdb=# create table logical_tb1(id int primary key,name varchar(20));
CREATE TABLE
desdb=#
注:逻辑复制的表结构需要手动在从库创建
2.6 在逻辑主库上创建发布
/** 在发布主库上创建发布pub1,注意实在sourcedb库下执行 */
sourcedb=# CREATE PUBLICATION pub1 FOR TABLE logical_tb1;
CREATE PUBLICATION
如果需发布多张表 则表名间用逗号(,)分割,如果需发布所有库,则将FOR TABLE 调整为FOR ALL TABLES。
此时可以查看到如下信息
sourcedb=# SELECT * FROM pg_publication;
pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate
---------+----------+--------------+-----------+-----------+-----------+-------------
pub1 | 10 | f | t | t | t | t
(1 row)
字段说明如下:
- pubname:指发布的名称
- pubowner:指发布的属主,可以和pg_user视图的usesysid字段关联查询得到属主具体信息
- puballtables:是否发布数据库中的所有表,t表示发布数据库中所有已存在的表和以后新建的表
- pubinsert:t表示仅发布表上的INSERT操作
- pubupdate:t表示仅发布表上的UPDATE操作
- pubdelete:t表示仅发布表上的DELETE操作
2.7 在逻辑从库上创建订阅
desdb=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.56.32 port=5432 user=logical_repl dbname=sourcedb password=logical_repl' PUBLICATION pub1;
NOTICE: created replication slot "sub1" on publisher
CREATE SUBSCRIPTION
创建成功后,可以在逻辑主库上查询到如下信息:
sourcedb=# SELECT slot_name,plugin,slot_type,database,active,restart_lsn FROM pg_replication_slots where slot_name='sub1';
slot_name | plugin | slot_type | database | active | restart_lsn
-----------+----------+-----------+----------+--------+-------------
sub1 | pgoutput | logical | sourcedb | t | 0/6022D30
(1 row)
在逻辑从库上可以查询到如下信息:
desdb=# SELECT * FROM pg_subscription;
subdbid | subname | subowner | subenabled | subconninfo | subslotname | subsynccommit | subpublications
---------+---------+----------+------------+---------------------------------------------------------------------------------------+-------------+---------------+-----------------
24995 | sub1 | 10 | t | host=192.168.56.32 port=5432 user=logical_repl dbname=sourcedb password=logical_repl | sub1 | off | {pub1}
(1 row)
2.8 给复制账号授权
因为步骤2.3中只创建了复制账号并未对需要复制的表进行授权,因此,此时逻辑从库的日志中有如下错误
2019-10-10 15:57:21.847 CST [27443] ERROR: could not start initial contents copy for table "public.logical_tb1": ERROR: permission denied for table logical_tb1
2019-10-10 15:57:21.848 CST [24722] LOG: background worker "logical replication worker" (PID 27443) exited with exit code 1
因此 ,现在需要对复制用户授权。
sourcedb=# GRANT USAGE ON SCHEMA public TO logical_repl;
GRANT
sourcedb=# GRANT SELECT ON logical_tb1 TO logical_repl;
GRANT
授权后,显示正常
2019-10-10 16:00:25.959 CST [28204] LOG: logical replication table synchronization worker for subscription "sub1", table "logical_tb1" has started
2019-10-10 16:00:25.967 CST [28204] LOG: logical replication table synchronization worker for subscription "sub1", table "logical_tb1" has finished
2.9 测试数据同步
在逻辑主库插入数据
/** 在主库插入数据 */
sourcedb=# insert into logical_tb1(id,name) values(1,'a'),(2,'bca');
INSERT 0 2
在逻辑从库查看结果
/** 查看数据是否同步完成 */
desdb=# select * from logical_tb1;
id | name
----+------
1 | a
2 | bca
(2 rows)
由此可见数据已同步完成。
2.10 添加复制所需的表
在逻辑主库和逻辑从库均添加一张新表,并添加到发布列表中
/** 主库上创建表结构 */
sourcedb=# create table logical_tb2(id int primary key ,addr varchar(100));
CREATE TABLE
sourcedb=#
/** 从库上创建表结构 */
desdb=# create table logical_tb2(id int primary key ,addr varchar(100));
CREATE TABLE
/** 在主库上给逻辑复制账号授权 */
sourcedb=# GRANT SELECT ON logical_tb2 TO logical_repl;
GRANT
/** 添加新表至发布列表 */
sourcedb=# ALTER PUBLICATION pub1 ADD TABLE logical_tb2;
ALTER PUBLICATION
/** 在主库查看发布列表中的表名 */
sourcedb=# SELECT * FROM pg_publication_tables;
pubname | schemaname | tablename
---------+------------+-------------
pub1 | public | logical_tb1
pub1 | public | logical_tb2
(2 rows)
此时已加入一张表进入发布列表中。
此时在主库写入数据,查看从库情况如下:
/** 主库插入一条记录 */
sourcedb=# insert into logical_tb2(id,addr) values(1,'beijing');
INSERT 0 1
/** 此时在逻辑从库查看,结果却没有数据 */
desdb=# select * from logical_tb2;
id | addr
----+------
(0 rows)
因为还需要在从库刷新一下订阅
/** 此时在从库刷新订阅 */
desdb=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION;
/** 刷新完成后再查数据已经有数据了 */
ALTER SUBSCRIPTION
desdb=# select * from logical_tb2;
id | addr
----+---------
1 | beijing
(1 row)
至此,PostgreSQL的逻辑复制也部署完毕。
3. 物理复制与逻辑复制特点和应用场景
PostgreSQL的逻辑复制与物理复制的差异比较突出,在使用中可以根据其特点选择使用哪种复制方式。
- 逻辑订阅,适合于发布端与订阅端都有读写的情况。
- 逻辑订阅,更适合于小事务,或者低密度写(轻度写)的同步。如果有大事务、高密度写,逻辑订阅的延迟相比物理复制更高。
- 逻辑订阅,适合于双向,多向同步。
- 物理复制,适合于单向同步。
- 物理复制,适合于任意事务,任意密度写(重度写)的同步。
- 物理复制,适合于HA、容灾、读写分离。
- 物理复制,适合于备库没有写,只有读的场景。
相关推荐
- jdk17安装和配置环境变量(jdk安装步骤环境变量配置)
-
简单介绍JDK17是Java的一个长期支持(LTS)版本,于2021年9月发布。作为LTS版本,它将获得Oracle的长期支持,这意味着会获得安全更新和错误修复,直到2...
- jdk8安装和配置环境变量(jdk8配置环境变量win10)
-
简单介绍JDK8是Java开发工具包的一个重大版本,于2014年3月发布。它引入了许多重要的新特性,极大地改进了Java编程的体验,并提高了代码的效率和可读性。总结JDK8是一...
- Java开发环境的准备流程!(java开发环境的准备流程有哪些)
-
准备开发环境工欲善其事,必先利其器。在学习本书的技术内容之前,应先将开发环境搭建好。本书所涉及的基础环境将在本章准备,包括JDK、IntelliJIDEA和Maven。如果读者对这些环境较为熟悉,可...
- skywalking-全链路跟踪(链路追踪sleuth)
-
一、概述1、skywalking简介SkyWalking是一款广受欢迎的国产APM(ApplicationPerformanceMonitoring,应用性能监控)产品,主要针对微服务、Clou...
- Oracle项目管理系统之成本状态跟踪
-
卷首语成本费用管理模块功能分为公司级、项目级两个层级,其中公司级功能包括概预算管理、概预算定额管理、预算模板管理,以及控制估算管理等功能。费用与成本成本费用管理主要是为了合理利用资金资源,控制企业的成...
- 从入门到精通,Java最全学习路线(java自学路线)
-
最近好多小伙伴询问,该如何学习java?那些视频适合零基础学习呢?大多数都是一些刚入门的新手,还不了解这个行业,也不知道从何学起,开始的时候非常迷茫,在这给大家整理出一些学习路线。Java学习路线在这...
- SPARC M7最新技术 甲骨文首度在台发表
-
甲骨文首度在台发表SPARCM7最新技术,宣布推出全新SPARC系统產品系列,採用革命性的32内核、256执行绪SPARCM7微处理器。这套SPARC系统提供:先进的入侵防护和加密的Securit...
- 轻量化的企业级OLAP方案2(轻量化ar)
-
上一篇文章讲了一个轻量化的企业级OLAP方案,这一篇文章继续介绍另外一个方案。方案2:Greenplum1Greenplum介绍1.1Greenplum概念Greenplum数据库是一种基于Po...
- 时序数据库在水电站领域的应用(时序数据库优缺点)
-
大家好,上期经过了王宏志教授对数据库前沿领域的介绍,不知道小伙伴们是否对数据库领域有了更深的认识呢,本期让我们回归时序数据库,再来聊一聊时序数据库在水电站领域的应用。本文仅代表个人观点,如有偏颇之处,...
- 数据库SQL引擎比较(数据库引擎有哪些,有什么区别)
-
数据库SQL引擎的典型工作机制及详细分析如下,涵盖查询处理全流程中的核心机制与实际案例:一、SQL引擎核心处理流程1.解析与校验阶段词法/语法解析:SQL语句被拆解为Token序列,构建...
- Ubuntu系统密码(root密码)的修改方法
-
本文介绍在Linux系统的Ubuntu电脑中,修改账户用户密码(同时也修改了root用户密码)的方法。首先,如果此时处于登录页面(也就是意识到自己忘记密码的那个页面),就先点击右上角的关闭按钮...
- TablePlus:一个跨平台的数据库管理工具
-
TablePlus是一款现代化的跨平台(Window、Linux、macOS、iOS)数据库管理工具,提供直观的界面和强大的功能,可以帮助用户轻松管理和操作数据库。TablePlus免费版可以永久...
- 云满足用户对通过单一视图了解整体运营和数据的需求
-
ZD至顶网软件频道消息:云在简化IT和业务的同时也带来了新问题,这很有趣,不是吗?毫无疑问,云大幅降低了企业运行基础设施和应用的复杂性和成本;但您仍然面临一个老生常谈的问题——孤岛,只不过这次是在云...
- SQL_TOP(显示数据条数)(sqlserver显示查询的行数)
-
(8)SELECT(9)DISTINCT(11)<topNum><selectlist>(1)FROM[left_table](3)<join_type>...
- php搭建小型部门网站(php构建网站)
-
熟悉前端html,js,css,后端熟悉php,python,java只能称得上一般,还有很多坑待踩。鉴于所学很杂,决定利用对业务的熟悉来搞一个部门网站来简化大家的工作流程。初步设计方案后端用p...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)