PostgreSQL逻辑复制与CDC
内容提要
PostgreSQL逻辑复制基于WAL实现实时CDC,通过复制槽跟踪消费进度,发布定义表过滤,WAL发送进程推送变更。需设置wal_level=logical、复制角色和发布,消费者用复制协议流式接收行级变更,可转发至Kafka等系统。
延伸解读
逻辑复制与物理复制的区别
逻辑复制基于WAL,但传输的是行级变更(如INSERT、UPDATE),而非物理字节。物理复制要求备库与主库文件布局一致,而逻辑复制可跨版本、跨数据库,甚至发送到非数据库系统(如Kafka)。理解这一区别有助于根据需求选择复制方式:需要完整数据库镜像时用物理复制,需要灵活数据分发时用逻辑复制。
复制槽的潜在风险
复制槽是服务端持久化的书签,即使消费者离线也会保留,并阻止WAL清理。若消费者长期断开或槽被遗弃,WAL会无限增长,可能导致磁盘耗尽。因此,需监控复制槽状态,及时删除不再使用的槽,并合理设置max_replication_slots以限制数量。
复制身份对UPDATE/DELETE的影响
复制身份决定UPDATE和DELETE消息中包含哪些旧行信息。默认使用主键,但若表无主键,需设为FULL以包含整行,否则消费者无法正确匹配变更。这增加了WAL体积,但确保数据一致性。设计表结构时,应优先考虑主键或唯一索引,以平衡WAL开销和复制可靠性。
Q&A
PostgreSQL逻辑复制是什么?
PostgreSQL逻辑复制是一种基于WAL(预写日志)的机制,它允许外部消费者实时接收数据库中的行级变更(INSERT、UPDATE、DELETE、TRUNCATE)。它通过PostgreSQL自身的协议在TCP连接上传输解码后的行级事件,是变更数据捕获(CDC)的基础。
如何配置PostgreSQL以启用逻辑复制?
需要修改postgresql.conf设置wal_level=logical,并设置max_replication_slots和max_wal_senders。然后在pg_hba.conf中允许复制连接,创建具有REPLICATION属性的用户,设置表的副本标识(如使用主键或FULL),创建发布(Publication),最后通过复制协议连接并开始消费。
wal_level=logical与wal_level=replica有什么区别?
wal_level=replica记录足够的信息用于物理复制和归档,而wal_level=logical在replica的基础上额外记录行级变更数据(如列值和元组映像),使得逻辑解码能够重建有意义的行级事件。因此,逻辑复制需要wal_level=logical。
复制槽(Replication Slot)的作用是什么?
复制槽是服务器端的书签,用于跟踪消费者在WAL中的读取位置,确保服务器不会删除消费者尚未处理的WAL段。每个CDC消费者需要自己的复制槽,槽是持久的,即使消费者离线也会保留,直到显式删除。
发布(Publication)在逻辑复制中起什么作用?
发布定义了哪些表的数据会被复制,以及哪些操作(如INSERT、UPDATE、DELETE)会被包含。它作为过滤器,可以指定特定表、特定操作、列子集或行过滤器。发布在发布者(源)端创建。
逻辑复制如何处理没有主键的表的UPDATE和DELETE?
对于没有主键的表,需要将副本标识设置为FULL,这样在UPDATE和DELETE消息中会包含旧行的所有列值,以便消费者识别受影响的行。如果设置为NOTHING,则UPDATE和DELETE操作将无法被消费者应用。
逻辑复制使用什么协议进行数据传输?
逻辑复制使用PostgreSQL的流复制协议,该协议基于TCP连接(默认端口5432),使用PostgreSQL自定义的二进制协议。它不是HTTP,而是支持流式传输的专用协议,服务器可以持续推送变更而无需客户端轮询。
逻辑复制与物理复制有什么区别?
逻辑复制操作在逻辑概念(行、列、表)层面,传输行级变更,可以跨版本、跨数据库类型;物理复制操作在物理层面(文件偏移、页号),传输原始字节,要求主备库版本和结构完全一致。逻辑复制通常用于CDC,物理复制用于高可用。