背景

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

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. 基于keras的残差网络

    1 前言 理论上,网络层数越深,拟合效果越好.但是,层数加深也会导致梯度消失或梯度爆炸现象产生.当网络层数已经过深时,深层网络表现为"恒等映射".实践表明,神经网络对残差的学习比对 ...

  2. jq中的正则

    正则匹配表达式 \w \s \d \b . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 等价于 '[A-Za-z0-9_]'. \s 匹配任意的空白符 \d 匹配数字 \b 匹配单 ...

  3. 【Azure Redis】Redis客户端出现15分钟的超时异常

    问题描述 客户端使用 Lettuce.io 连接 Azure Redis,出现了长达15分钟的Timeout异常. 问题解答 Azure Redis作为PaaS服务,由于一些平台的升级操作而引发的故障 ...

  4. 【Azure 环境】使用 az ad group create 时候遇见 Insufficient privileges to complete the operation

    问题描述 使用China Azure,通过Azure CLI 创建AAD组报错,提示权限不足 Insufficient privileges to complete the operation # 使 ...

  5. 【Azure 应用服务】App Service 默认开放端口说明, 如何禁用Web app的端口号? 

    问题描述 基于安全的角度来考虑,在网站上线之前用户会对自己的网站进行安全扫描,以防网站因为某些漏洞而被非法攻击. 而在扫描过程中,会发现除了 80 和 443 之外的一些其他端口也被开放了.例如:45 ...

  6. 【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析

    问题描述 Azure Redis Cluster 在增加分片数时失败,错误消息为: ResponseBody: { "error": { "details": ...

  7. 简单配置Sql专家云

    一.实例配置 1.添加实例 点击全面诊断实例配置,右上角点击添加. 2.填写实例信息 根据下图填写对应的信息,连接测试成功后点击保存. 3.添加完成 4.修改实例 找到对应的实例,点击下图蓝色框修改即 ...

  8. CUDA指针数组Kernel函数

    技术背景 在前面的一篇文章中,我们介绍了在C++中使用指针数组的方式实现的一个不规则的二维数组.那么如果我们希望可以在CUDA中也能够使用到这种类似形式的不规则的数组,有没有办法可以直接实现呢?可能过 ...

  9. git svn 提交代码日志填写规范 BUG NEW DEL CHG TRP gitz 日志z

    git svn 提交代码日志填写规范 BUG NEW DEL CHG TRP gitz 日志z

  10. Dreamweaver基础教程:学习JavaScript

    目录 简介 用法 输出 语法 字面量 变量 操作符 语句 关键字 注释 数据类型 函数 函数表达式 Function() 构造函数 自调用函数 箭头函数 arguments 对象 使用构造函数调用函数 ...