逻辑复制,就是那个容易出错,效率低,容易造成主从数据不一致的技术. 可能在提及逻辑复制,就会得到上面的评论,或许是MYSQL 给人的第一印象(其实我不认为逻辑复制有多不好)。当然对比物理复制 Stream Replication 来说,逻辑的复制的效率的确是不高,并且上面被吐槽的地方都是有的。
但逻辑复制有什么好
1 我只要XX 库的数据 ,或XX表的数据,物理复制可以吗?
2 我要做汇聚库,要 XX 库表 XX 库表 到 一个库中,进行数据分析?
3 诶,我复制的库的数据,可能的改改,在从库上改改试试,那我改的时候你就别在复制了,我改完做完测试后,在还原我刚才改的数据,你在继续复制OK ?
4 诶,我们要将目前的PG 10 的表复制到PG 11
那物理复制-------- NO WAY
所以一项技术的好坏先要看他是否能满足需求,所以逻辑复制好不好要看他是否能满足上面的需求。
OK 我们先来将一个测试库导入到 PG 的数据库中,大家如果测试可以使用dvdrental 库作为 simple 库。
我们举例下面就是我们要操作的数据库 dvdrental 中包含了15个表
1 我们将dvdrental 整体数据库中的所有的表都复制到另一个PG的服务器中。
1 创建一个publication,在 dvdrental 数据库中执行如下命令创建一个 dvdrental 为命名的所有表的 publication
CREATE PUBLICATION dvdrental FOR ALL TABLES;
2 对源数据库进行备份,采用 pg_dump pg_resotre 来进行(不清楚的同学请百度一下,很简单)
3 在将源数据库恢复到了目的库的 dvdrental 库后
CREATE SUBSCRIPTION publication CONNECTION 'host=192.168.198.200 dbname=dvdrental user=publication password=1234.com port=5432' PUBLICATION dvdrental;
然后我们可以查看当前复制是否被建立。
select * from pg_stat_replication;
看上去还是比较简单的,但上面的操作有以下几个问题
1 我备份的数据是整体备份数据, 还原到目的库,还是仅仅备份表结构然后让主从逻辑去同步数据。
这个问题的两方面看
1 逻辑备份不需要你备份数据库,只要有表结构即可,并且表结构也不要求是一定和原表的表结构一致,只要是不比原表的字段少,类型大致一致即可。
2 那既然逻辑备份可以补足数据,为什么还要进行备份数据的工作,在恢复到目的地,这里有一个问题,就是数据量的问题,如果数据量比较啊,则数据补足的时间会比较慢,所以可以先备份数据过去,在进行复制。
但这里又有一个问题,如果我在备份的时候带有数据,到目的地,在建立复制,是否有数据丢失的情况,因为我在备份恢复的过程中,也有数据写入。
带着这个问题我们做下一个实验
1 我建立一个publication
2 我备份数据库
3 期间我添加数据在publication端
4 我恢复数据库
5 建立subscription查看 在3 好期间的数据是否能补齐
最后的结果是,不能补齐,这和我试想的是一样的,首先我们建立publication 的时候,并没有建立复制槽,而复制槽的建立,是开始数据复制的开始, 所以在复制槽建立前如果在publication端录入的数据,并且在 subscription 端创建订阅时 采用 with (copy_data
= false) 那必然是不会有复制槽建立前备份后录入的数据。
但如果我们不实用 copy_data = false 则在同步数据的时候,要不就等待的时间较长,(如果数据量足够大,publication端的 wal_log 的目录会保留很多来不及进行复制的数据操作记录),并且还会有很多重复主键的错误提示,因为复制是从头开始的,通过主键的方式,而备份的数据必然和部分publication的数据重合,但数据是不会丢失的。
这是一点,在做逻辑复制时需要考虑的问题
另一个点是,我在做测试的时候很怪异,我想停止订阅服务,
alter subscription 订阅的名字 disable
提示 订阅不存在
drop subscription 订阅的名字
删除订阅 也提示订阅不存在
无奈之下只能关闭从库,删除publication 和 复制槽
而留下的结果也很有趣,就是连续做了两次 publication subscription 会出现同样名字的subscription的残留,并且尝试删除也失败。
到目前为止,逻辑复制还有一些问题需要搞清楚,在学习的过程中,发现有些怪异的问题并未有明确的文档或者解释,包含英文方面的也目前也未找到特别详细的内容。