背景

据实施人员反馈发现如下报错:

FATAL: terminating connection due to conflict with recovery

DETAIL: User query might have needed to see row versions that must be removed.

HINT: In a moment you should be able to reconnect to the database and repeat your command.

很明显报错说明发生了查询冲突现象,下面来讲解并分析一下流复制冲突以及如何避免。

提前说明:一切避免冲突的手段都可能导致主节点的垃圾回收做无用功, 费劲IO和CPU却不回收垃圾.

什么是复制冲突?

每当恢复过程无法将 WAL 信息从主服务器应用到备用服务器时,就会发生复制冲突,因为主库的更改会造成备库查询中断。

复制冲突类型

快照复制冲突

这是最常见的复制冲突。基于mvcc特性。

如果主库VACUUM 处理表并删除死元组,则可能发生快照冲突。此删除将在备用服务器上replay。现在备用数据库上的查询可能在主数据库上的 VACUUM 之前开始(它有一个较旧的快照),所以它仍然可以看到应该删除的元组。这构成了快照冲突。

锁复制冲突

备用服务器上的查询在它们正在读取的表上使用ACCESS SHARE锁。因此,必须在备用数据库上重放主数据库上的任何 ACCESS EXCLUSIVE 锁(与 ACCESS SHARE 冲突),例如 DROP TABLE、TRUNCATE 和许多 ALTER TABLE 等语句。如果备用数据库应该在查询使用的表上重放这样的锁,我们就会发生锁冲突。

buffer pin复制冲突

减少对 VACUUM 需求的一种方法是使用 HOT 更新。然后在主节点上的任何查询访问具有仅死堆的页面并且可以获得排他锁将修剪HOT链。(查询修改时页面,缩短热链。加轻量级锁)数据库总是持有这样的页面锁定时间很短,因此与主节点上的处理没有冲突。页面锁定还有其他原因,但这可能是最常见的原因。

When the standby server should replay such an exclusive page lock and a query is using the page (“has the page pinned”), you get a buffer pin replication conflict. Pages can be pinned for a while, for example during a sequential scan of a table on the outer side of a nested loop join. (当从库上有nest loop join, 并且外表是全表扫描, 而且刚好这个外表有prune HOT chains的wal replay时, 这个replay可能长时间等待).

HOT chain pruning can of course also lead to snapshot replication conflicts. (HOT chain pruning也会导致snapshot 冲突)

罕见的复制冲突

  • 死锁复制冲突:在使用从主数据库重放 WAL 所需的共享缓冲区时对备用块的查询。数据库会立即取消这样的查询。
  • 表空间复制冲突:一个表空间在备用服务器上的 temp_tablespaces 中,并且一个查询在那里有临时文件。当主数据库发生 DROP TABLESPACE 时,我们会遇到冲突。在这种情况下,数据库会取消备用数据库上的所有查询。
  • 数据库复制冲突:如果备用数据库在数据库上有活动会话,则 DROP DATABASE 的复制会导致冲突。在这种情况下,数据库会终止与备用数据库的所有连接。

监控复制冲突

统计视图 pg_stat_database_conflicts 包含自上次统计重置以来发生的所有复制冲突的详细说明。必须在备用服务器而不是主服务器上查看该视图,因为那是发生复制冲突的地方。

请注意,此视图不会显示发生的所有复制冲突,它仅显示导致在备用数据库上取消查询的那些。

避免流复制冲突

避免所有冲突

显然,如果备库上没有查询,就不会有复制冲突。因此,可以在备库上设置 hot_standby=off,则不会发生冲突问题。

但是,只有备库专门用于高可用性才可以使用上面的配置,如果用于读写分离场景,这样做就违背初衷了。

避免快照冲突

减少此类冲突的方法是防止主库删除备库上仍然可见的死元组。可以通过以下两个参数实现:

  • 将主库上的 hot_standby_feedback 设置为on。它阻止VACUUM 移除最近死亡的元组,就有可能导致主库上的表膨胀。默认情况下,没有启用该设置。
  • 将主库上 vacuum_defer_cleanup_age 参数设置为大于0的值。VACUUM将不会立即清除死元组,除非超过了 vacuum_defer_cleanup_age 指定的事务数据的旧值。还不如 hot_standby_feedback 那么具体明确,还可能导致表膨胀。

hot_standby_feedback = on 将消除大多数快照复制冲突,但不一定消除buffer pin冲突。

避免锁冲突

避免锁冲突的明显措施是不发出对表使用ACCESS EXCLUSIVE锁的语句。例如:DROP TABLE、TRUNCATE、LOCK、DROP INDEX、DROP TRIGGER、ALTER TABLE。

但是有一种ACCESS排他锁是无法通过这种方式避免的:来自VACUUM截断的锁。当VACUUM完成了对表的处理,并且表末尾的页变为空时,它会尝试在表上获得一个短的ACCESS EXCLUSIVE锁。如果成功,它将截断空页并立即释放锁。虽然这类锁不会中断主库上的处理,但它们可能导致备库上的复制冲突

避免VACUUM截断的方法

  1. 从KingbaseESV8R6开始,可以针对单个表的禁用此功能
ALTER TABLE test SET(vacuum_truncate = off);
  1. 将主库上的old_snapshot_threshold设置为-1以外的值。这会禁用VACUUM截断,这是未被记录的副作用。

避免buffer pin冲突

没有很好的方法可以避免这些冲突。也许可以减少 HOT 更新的数量,但这会损害主节点的性能。

解决复制延迟的代价

当hot_standby_feedback=on。

如果备库出现了LONG QUERY,或者Repeatable Read的长事务,并且主库对备库还需要或正查询的数据执行了更新并产生了垃圾时,主库会保留这部分垃圾版本(与vacuum_defer_cleanup_age参数效果类似)。

代价1,主库对应对象膨胀,因为垃圾版本要延迟若干个事务后才能被回收。

代价2,重复扫描垃圾版本,重复耗费垃圾回收进程的CPU和IO资源。(n_dead_tup会一直处于超过垃圾回收阈值的状态,从而autovacuum 不断唤醒worker进行回收动作)。

当主库的 autovacuum_naptime=很小,同时autovacuum_vacuum_scale_factor=很小时,尤为明显。

代价3,如果期间发生大量垃圾,垃圾版本可能会在事务到达并解禁后,爆炸性的被回收,产生大量的WAL日志,从而造成WAL的IO峰值。

当设置参数max_standby_archive_delay, max_standby_streaming_delay时,

代价,如果备库的QUERY与APPLY(恢复进程)冲突,那么备库的apply wal会出现延迟,也许从备库读到的是很久以前的数据,导致备库的数据过于陈旧。

请注意,如果备用服务器在应用 WAL 方面落后,则您无需在故障转移期间丢失更多数据——WAL 信息仍会流式传输到备用服务器并写入 sys_wal。但是备用数据库需要更长的时间才能追平,因此有故障转移时间会增加的风险。

结论

对于读写分离的集群模式架构,想解决复制冲突,

则必须调整 hot_standby_feedback、max_standby_streaming_delay 和 Vacuum_truncate 存储参数,以尽可能少地取消查询,同时避免过度的表膨胀和长时间的复制延迟。

解决流复制会造成表膨胀,所谓鱼与熊掌不可兼得。如果可以和业务协调,尽量不要把备库的查询和主库的DDL语句放同一时间段执行。

KingbaseES V8R6 流复制冲突分类以及对应解决方案的更多相关文章

  1. KingbaseES V8R6集群部署案例之---Windows环境配置主备流复制(异机复制)

    案例说明: 目前KingbaseES V8R6的Windows版本不支持数据库sys_rman的物理备份,可以考虑通过建立主备流复制实现数据库的异机物理备份.本案例详细介绍了,在Windows环境下建 ...

  2. KingbaseES V8R6集群部署案例之---Windows环境配置主备流复制(同一主机)

    案例说明: 目前KingbaseES V8R6的Windows版本不支持数据库sys_rman的物理备份,可以考虑通过建立主备流复制实现数据库的异机物理备份.本案例详细介绍了,在Windows环境下建 ...

  3. KingbaseES R6 手工创建主备流复制案例

    ​ 数据库版本: TEST=# select version(); version ---------------------------------------------------------- ...

  4. KingbaseES R6 集群创建流复制只读副本库案例

    一.环境概述 [kingbase@node2 bin]$ ./ksql -U system test ksql (V8.0) Type "help" for help. test= ...

  5. KingbaseES R6 主备流复制集群创建级联复制案例

    案例环境: 数据库: test=# select version(); version -------------------------------------------------------- ...

  6. 命令行部署KingbaseES流复制+切换测试

    建立系统数据库安装用户组及用户,在所有的节点执行 root用户登陆服务器,创建用户组及用户并且设置密码 groupadd -g 2000 kingbase useradd -G kingbase -g ...

  7. KingbaseES V8R6集群维护案例之--单实例数据迁移到集群案例

    案例说明: 生产环境是单实例,测试环境是集群,现需要将生产环境的数据迁移到集群中运行,本文档详细介绍了从单实例环境恢复数据到集群环境的操作步骤,可以作为生产环境迁移数据的参考. 适用版本: Kingb ...

  8. KingbaseES V8R6集群运维案例之---repmgr standby promote应用案例

    案例说明: 在容灾环境中,跨区域部署的异地备节点不会自主提升为主节点,在主节点发生故障或者人为需要切换时需要手动执行切换操作.若主节点已经失效,希望将异地备机提升为主节点. $bin/repmgr s ...

  9. Oracle 流复制实践笔记

    最近因为业务需求,需要在两个数据库之间做双向实时同步,遂实践了一把Oracle的流复制,遇到了很多疑难问题,最终也貌似成功,现记录如下. 我是使用OEM来实现流复制的. 10.进行流复制的两个数据库的 ...

  10. postgresSQL主从流复制安装

    命令行运维: https://blog.csdn.net/zhangzeyuaaa/article/details/77941039 安装流程: 先准备类库: yum -y install readl ...

随机推荐

  1. 【Unity3D】空间和变换

    1 空间 1.1 左右手坐标系及其法则 1.1.1 左右手坐标系 左手坐标系与右手坐标系 ​ Unity 局部空间.世界空间.裁剪空间.屏幕空间都采用左手坐标系,只有观察空间采用右手坐标系. ​ 左右 ...

  2. Java设计模式-中介者模式Mediator

    介绍 中介者模式(Mediator Pattern),用一个中介对象来封装一系列的对象交互.中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 中介者模式属于行 ...

  3. image could not be accessed on a registry to record its digest

    问题说明: 在管理节点执行docker stack xxx 方式运行服务,报如题错误. 问题原因: docker swarm运行需要一个镜像仓库才行,所有节点都去这个仓库统一镜像. 来看下官方的解释: ...

  4. SpringBoot+Shiro+LayUI权限管理系统项目-7.实现用户管理

    1.说明 只讲解关键部分,详细看源码,文章下方捐赠或QQ联系捐赠获取. 2.功能展示 包括用户增删改查和分配角色. 3.业务模型 @Data @EqualsAndHashCode(callSuper ...

  5. 最简最快了解RPC核心流程

    本文主要以最简易最快速的方式介绍RPC调用核心流程,文中以Dubbo为例.同时,会写一个简易的RPC调用代码,方便理解和记忆核心组件和核心流程. 1.核心思想 RPC调用过程中,最粗矿的核心组件3个: ...

  6. 【LeetCode排序专题01】由旋转数组的最小数字引出的关于排序算法的讨论(冒泡排序、二分查找+暴力法)

    旋转数组的最小数字 剑指 Offer 11. 旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一 ...

  7. 矩池云上 git clone --recursive 出错,怎么解决

    遇到问题 有时候安装包教程里 git clone 的时候会出现以下错误: git clone --recursive https://github.91chi.fun/https://github.c ...

  8. C语言初学习——易错点合集(长篇)

    转义字符 例题一 int main() { char s[] = "012xy\08s34f4w2"; int i, n = 0; for (i = 0; s[i] != 0; i ...

  9. Java 从键盘读入学生成绩 找出最高分 并输出学生等级成绩 * 成绩>=最高分-10 等级为’A‘ * 成绩>=最高分-20 等级为’B‘ * 成绩>=最高分-30 等级为'C' * 其余 等级为’D‘

    1 /* 2 * 从键盘读入学生成绩 找出最高分 并输出学生等级成绩 3 * 成绩>=最高分-10 等级为'A' 4 * 成绩>=最高分-20 等级为'B' 5 * 成绩>=最高分- ...

  10. AutoTipZen 实时根据文字是否溢出 提示title

    AutoTipZen 实时根据文字是否溢出 提示title <template> <div ref="autoTipRef" @mouseover="o ...