背景

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

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 NavMeshObstacle组件 ​ 导航系统.分离路面导航中路障都是静态的,程序运行过程中烘焙的导航网格一直不变,本文将进一步讲解动态路障场景下导航的实现. ​ 对于动态路障游戏对象,除了要设 ...

  2. 【framework】DisplayContent简介

    1 前言 ​ DisplayContent 用于管理屏幕,一块屏幕对应一个 DisplayContent 对象,虽然手机只有一个显示屏,但是可以创建多个 DisplayContent 对象,如投屏时, ...

  3. 解决:Not found the kernel library or the kernel library is invalid

    问题说明: 今天运行一个E语言写的程序报错, 看样子是缺少核心依赖库. 解决方法 去下载个易语言安装包安装一下即可.比如我安装的是: 易语言5.6完美破解版(精简版).exe 下载地址:https:/ ...

  4. SBI信息反馈法

    https://baijiahao.baidu.com/s?id=1605128367255769158&wfr=spider&for=pc

  5. Centos8上安装Redis5.X

    一.下载Redis 下载地址:wget http://download.redis.io/releases/redis-5.0.7.tar.gz 解压:tar -xzvf redis-5.0.7.ta ...

  6. Java11改进的垃圾回收器

    传统的C/C++等编程语言,需要程序员负责回收已经分配的内存.显示进行垃圾回收是一件比较困难的事情,因为程序员并不总是知道内存应该何时被释放.如果一些分配出去的内存得不及时回收,就会引起系统运行速度下 ...

  7. Java //数组的反转

    1 //数组的反转 2 //方式一 3 System.out.println("数组的反转"); 4 5 // for(int i = 0; i <arr.length/2; ...

  8. liquibase customChange

    liquibase customChange liquibase changeset 执行Java代码. liquibase支持yml等文件,支持引入sql文件,还支持Java这种方式执行change ...

  9. 学习ASP.NET Core Razor 编程系列文章目录

    学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二--添加一个实体 学习ASP.NET Core Razor 编程系列三--创建数据表及创建项目 ...

  10. KeyCastOW win10 屏幕显示按键 - 屏幕录像用

    KeyCastOW win10 屏幕显示按键 - 屏幕录像用 https://gitee.com/itas109/KeyCastOW/releases/v2.0.2.5-cn