9 PostgreSQL 点对点多主表级复制-触发器篇|学习笔记

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,企业版 4核16GB
推荐场景:
HTAP混合负载
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 快速学习9 PostgreSQL 点对点多主表级复制-触发器篇

开发者学堂课程【PostgreSQL 快速入门9 PostgreSQL 点对点多主表级复制-触发器篇】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/16/detail/68


9 PostgreSQL 点对点多主表级复制-触发器篇

 

内容介绍:

一、表级复制简介

二、 操作

三、回顾


一、表级复制简介

前面讲过数据库的集群级的复制,也就是数据库的流复制,相当于是把整个数据库的提取通过 xlog 的一些变更复制到 standby 节点sandby 节点跟主数据库保持完全一致。

当然一些不写 xlog 操作无法通过复制给它推广。比如 onload table 创建的像临时表以及 logo 的推广都不会写xlog,所以无法使用流复制。还有比如哈希索引也是不能使用流复制来复制。

表级复制能很的解决上述问题如果使用流复制复制 standby 节点,它只能作为只读的节点。如果要写,需要激活。

激活之后两个就是重组节点,无法通过 xlog 方法来复制到 standby 节点,也就是激活之后就是两个完全独立的口。

在某一些复制场景,比如只需要复制某一些表或者是某一些表里的数据的,并且复制过去的节点,同时也有读写的操作在这种情况下,使用复制无法满足需要,可以使用触发器来完成,或者是使用第三方的插件比如 Slony、londiste3bucardo、pgpool、pl/proxy。这些插件分为很多种一种是 sql 分发的方式来控制。比如 pgpool 相当于做中间件,对于要复制的数据,会在它下面配置数据库节点选择要复制到哪几个数,它相当于是帮你做sql分发的过程。

包括 pl/proxy 也可作为分发器来实现数据库的复制。然后还有一种是数据库端的触发器的复制。

比如 londiste3以及 slony 都是通过主节点上创建触发器,生成一些操作日志这些操作日志被作复制的sql语句发送给 standby 节点,然后在 standby 节点上去执行这些sql语句

触发器

首先来讲基于触发器的复制,通过 dblink ,postgere 支持 dblink。dplink 整个包的使用可以参考 dblink 的使用手册就是这篇 blog 里

https

blog.163.com/digoal@126/blog/static/163877040201321125220134写通用的触发器来实现multi-master 复制场景。

image.png

multi-master 指的是两个 master 节点,比如数据库A数据库B这两个数据库节点里面的表可以相互进行复制。也就是从A可以把数据复制到B或者从B类也可以把数据复制到A并且支持异步和同步的复制方法。

对于异步这种使用方法不是非常严谨,因为异步同时并发的操作一个表在使用这种触发器,可能会带来一些问题,可能造成在主数据库上执行的顺序和在 standby 节点上执行的事物顺序会有不一致或者其它情况。

但是使用同步就不会有上述问题。尽量使用同步复制,而不要去用异步复制。

 

二、操作

首先是创建角色,然后要创建 dplink 插件。比如要从30150这一台数据库复制到3.39数据库。这里版本是9.4的版本,然后另外一个是9.3.2版本。

image.png

这两个版本之间通过触发器方式可以复制。对于流复制,它就必须要一次因为这里是两个完全的独立的库。通过输入 create extension dblink 创建 dblink,dblink 已经存在,不需要创建。

另外的3.39库也需要创建,甚至可以从不同的数据库复制到另外的库。只是要使用不同数据的用户比如专门用于复制的用叫 test 的用户,可以给普通的权限。

输入 create test nosuperruser login encrypted password’test’然后允许它登录,设置密码。

然后在另外数据库。比如postgre 数据库也可以创建同名的角色。当然也可以创建不同的角色。

也就是在3.150数据库里面的表要复制到3.39的 postgre然后通过的用户一样与否关系不大

在创建用户之后,要赋予一定的权限,包括给它创建 SDM 等按照这篇 blog 来。

先创建角色。

Postgres =# create role local login encrypted password

LOCAL321;

CREATE ROLE

Postgres =# create role local login encrypted password

REMOTR321;

在另外一个数据库创建远程的角色,然后创建数据库。在3.150数据库创建 local 数据库,在3.39上创建 remote 数据库。

Postgres =# create database local owner local

CEATE DATABASE

postgres =#create database remote owner remote

CREATE DATABASE

postgres =#\c local postgres

Tou are now connected to database “ local ” as user

“ postgres ”

local=# create extension dblink

CREATE EXTENSION

local=#/c remote postgres

Tou are now connected to database ‘remote’as user postgres

remote = #create extension dblink

然后数据库创建完成之后,先连到 local 下面去创建 local 数据库。3.150上创建 extension,就是 dblink然后在远程库 remote 的功能也要创建因为要做 multi-master 的场景,也就是相互都要复制

数据库创建的报错。为这是开发版本,可能是开发的一些 bug。换成 pg9.2,这里也是创建角色。

image.png 

从9.2和9.3之间复制创建用户,创建 local 数据库,然后去创建 dblink远程的以及创建完成。,接下来在 local 里面创建schema

local=>/c local local

local=> create schema local

CREATE SCHEMA

local=>/c remote remote

You are now connected to database “remote" as user "remote

remote=> create schema remote

CREATESCHEMA

然后在remote库,也创建schema叫做remote。

接下来要在local里面去创建测试表,叫做OOC test。本例将使用联合索引

remote=>/c local local

You are now connected to database local" as user “local"

local=>create table loc_test (pkl int, pk2 text, info text,

crt_time times tanp(0), mod_time timestamp(0), primary

ikey(pk1,pk2)):

同时创建表一定要有 pk用 dblink 去复制的去生成比如本地有一条 sql 语句,在要生成远端执行的 sql 语句,还要调dblink 包里面的函数。

函数要求表必须要有 primary key。也就是被复制的表里面必须要有 primary key就是有 primary key 能够定位到每一条记录。

local=> select string

agg(positiontext,’’)int2vector,count(*) from

dblink_get_pkey(local loc_test’): string_agg|count

因为使用 dblink 的一些包去生成 sql 语句的,是需要用到比如 primary key 的 numbers 的 enter to the victor 的词,同时还要用到 primary key 字段。比如是两个字段创建的联合组建的话,这里就是2然后这是矢量。

image.png

比如在 sql 语句当中,select*from loc_test 它的组件的顺序,在整5个字段里面,它是排在1和2的,integer 的值就是1、2。如果组件是排在2、3位的,就是23。

使用 dblink _get_pkey 能够得到是它的 int2vector矢量,还可以得到它总共有多少个组件。

dblink_get_pkey(local loc_test’): string_agg|count

是用于获得一些图像信息的。select*from loc_test 能得到组件信息它的位置信息以及它的列名。count 是它总共有多少个,组总共有多少个字段。用于这种通过函数去创建 sql 语句的。

postgres=# \c remote remote

You are now connected to database "remote” as user "renote"

remote=> create table rmt_test (pkl int, ph2 text, info text,

crt_time timestump(0), mod time timestamp 0), prieary key (pkl, pk2)):

NOTICE: CREATE TABLE /PRIMARY KEY will create implicit index

“rat_test pkey" for table "rmt_test" CREATE TABLE

remote=> select string acc(position::text,’’)::int2vector,count(*) fron

dblink_get pkey(remote.rat_test’); string.agg|count

接下来,在远程库里面去创建远程表叫做int_test才是。表结构跟 ioc 一样,只是 schema 的名字和表不一样。

去查询的,也可以得到它的组件的矢量组件位置数量以及组建的包含 primary key 的列的数量。

local 和 remote 库回收 pg_user_rrappings public 权限可以不去做,因为只是把表的查询权限从 public 里面回收掉。如果在 user 里面配密码的话可以规避一些问题。

回收后要通过 db_link 去连接,

在 local 库创建 server

postgres=# /c local postgre

You are now connected to database "local" as user “postgres"

local=# CREATE FOREIGN DATA WRAPPER pOStresgl VALIDATOR

postgresql_fdw_vali dator:

CREATE FOREIGN DATA WRAPPER

locel=# CREATE SERVER dST FOREIGN DATA WRAPPER pOStgresgl

OPTIONS (hostaddr ’172.16.3.150’, port '9999’, donine

'remote'

options'-ctcp_keepalives_idle=60s-c

tcp_keepalivex_interval=10 -c tcp_keepalives_count=6 -c

application_name=aea_bbb_digosl’): CREATE SERVER

Local=# GRANT USAGE ON FOREIGH SERVER dst TO locel GRANT

local=# CREATE USER MAPPING FOR local SERVER dst OPTIONS

(user’remote’, password ’REMOTE321'): CREATE USER BAPPING

然后是 local 库里面,创建 server叫DST。DST 包含一些连接到远端的信息比如库名,端口。

39这监听端口是5432ip3.39数据库名是 remote选项指的是连接从3.150上创建的 server,连接过去的一些选项。

image.png

但是注意 application name 一定要配置并且两个要配置不一样,因为是使用触发器,才能够规避掉一些无限循环。比如在3.150上面触发触发器,并且生成映射语句通过 dblink 发送给这台主机。

然后让它去执行,并且这上面同时又有触发器,因为是做多复制。如果触发器在映射的,它也会触犯 in set,调用远程in set。也就相当于是150 inset 触发39的 inset,然后39inset 触发,触发了150 发 inset,就变成无限循环

所以要通过 application name 来分辨,如果是远程复制过来的 sql,触发器不做任何操作,不会导致无限的插入触发。

接下来就把 server 创建之后,把 server 的权限赋予 local创建给用户创建 mapper,也就是 server 使用 local 去连接,用 remote 去链接,也就是连接到3.39数据。

配之后,要要来到 remote 库去做配置。remote 库也是同样的道理,不再赘述。在触发器函数在写的,规避掉application name 就可以。注意端口的名字改1924其它不用改动。然后把权限赋予给 remote 用户

接下来如果是使用异步复制,会产生一些错误。打个比方,数据库刚不通,那在 local 和 remote 库创建异步复制错误 SQL 记录表。

create table sync_err rec(id serial8 prinary key,nsp_name

name,table_none name, dst_server text, dst query text

create time timestamp without time rone)

MO2wqazTICE CREATE TABLE will create implicil sequence

“sync_err_rec_id_seq" for serial colunn "zync_err_rec. id"

NOTICECREATE TABLE/PRIMARY KEY will create inplicit

index“sync_err_rec pkey for table "sync_err_rec

CREATE TABLE

错误的同步表要连到里面

image.png

这里面包含几个字段,id字段是组件,nsp_name 也就是 SDV 的名字如果同步错误,同步错误的表面是table_name。目标服务器dst指的是创建的server等等。

技术错误表创建之后,处理错误的函数。处理错误的函数,把它创立在不同的库下面。来函数里面一些含义。

image.png

limit 是错误记录表里面取出多少条数据,比如取出100条,如果当前是 standby 数据库不处理,否则在 server 表里字段叫 dst_server,用于连接远端数据库的server的。

然后取出来之后from date 锁住。比如现在正在处理 destination server 的一些记录,不允许当前有其它程序要去处理它

锁的处是能够使操作是串行的操作。尽量去使用函数同步复制,因为异步复制,如果并行操作,会带来一些事物的执行顺序可能会不一致问题。

比如主节点的事物咨询执行顺序,在多个事物中,有可能是事物B发生的错误但是事物C正常,最后执行事物的顺序跟在本地执行的顺序不一致。所以尽量要使用一些方法去规避重复问题。当然如果要严格意义上来完全一致最终还是需要去使用第三方的一些插件比较。

如果服务器server 渠道的是空,直接返回里面没有可以执行的记录,如果是取到,不是空,支持 DST server再去把里面的一批记录取出来,从错误的 record 表里面去取,然后把dst_query取出来。

同时还要把 id 要记下来,执行完之后要把数据从表里面删掉,因为就比如现在已经同步,一些错误同步记录就可以删掉。

删掉之后,然后就去建立连接。建立连接之前要判断当前会话是已经建立链接,通过 dblink get connection 就能够得到当前的链接列表如果包含的 nation name 是指定的取出来的 server 名,就不用重新建立连接。否则就通过dblink connect 命令去建立连接然后使用 db_link excute 这条命实施相当于是去算一些批量的语句,通过聚合函数,还有号聚合在一起。

使用 true如果远端执行失败,也直接会回滚能够确保不会有任何的问题,如果是 false,表示如果远端执行失败,还是继续返回,是不允许的。在处理错误的,必须要使用true

接下来就要建触发器

image.png

触发器它的返回类型是 trigger使用 PUPGCQ 来写的DST server 变量,是 foreign server 就是要把它复制到哪个server 上去。比如两个节点创建 DST,它的 server 名都叫 DST。

所以在配置的就是都叫 DST。然后连接不是非常重要,跟 density server 一样就可以。连接状态,连接状态是用dblink connect 函数连接之后产生状态通过状态可以去判断连接是否常。然后触发器的变量是促使用函数可以直接使用的变量比如 table 的 schema,是 table 的名字。也就是触发触发器的表,它是属于哪个 schema 的。同时它的表叫什。

目标表的 schema,要复制到其它 schema 的,要制定。v_query,是指使用三个 dblink 的函数得到的sql语句,然后把它放到dblink excute函数里面远程调用,也就相当于是 inset 语句,在触发器里面,通过函数去把它封装成inset语句,然后再通过 dblink excute 去执行 circle

update使用 delete insert 去模拟 update。因为使用 dblink 思考,update 无法完整

比如表叫做 test然后它的 pk 是 id 和 info 这两个字段,通过 update 指定它的字段的矢量,pk 的字段。矢量是1和2。它总共包含两个字段

image.png

圆的 pk 1和abc要把它变更成1和 bcd,变更出来的条件也变成 bcd。一般条件应该是 abc 劳务最后它等于bcd,所以bug,不能使用 update 去封装出远端执行。

这里通过 delete 和 insert 来替代 updata 的操作。因为在 updata 孵化器里面有 new 和 old 的 code。通过 new 和old the record delete 的话,就 delete order,

相当于没有用函数,用函数来得到 update 在远端的执行的 circle

v_dst_query text 是用于存储 v_query 修改后的语句,主要是修改目标 schema 和目标表,因为他们可能和原表名不一样上面三个,是从两个函数里面得到的所以它封装出来的是 schema 名和表名的话,保持修改 replace 即可

query update1是 delete 的 circle。然后 query update2是 insert的 circle,下面分别对应是修改后的 delete,是修改的 insert。

然后 v_pk vector 存储 pk 列的逻辑位置。对于9.0以及9.0以上的版本,它的逻辑位置是真正查询出来的位置。对于9.0以下的版本,比如8.4 8.3,它的逻辑列的位置物理位置

pk 的字段是函数要用到的pk 的名称数组比如 pk1pk2,pk 值的数组,是 text 的数组。

临时的 pk 数组,比如有多个 pk 值,其实是通过聚合把它封装在一起。

excute 状态是调用 dst 的一些返回值。如果使用异步的话,储返回如果是同步的话,它就没有意义。

然后接下来是多组复式相关,通过 appliction name 来防止死循环。

image.png

客户端 v_application_name_cli text

v_application_name_check text是要检测的端口,

v_pg_backend_pid int 可以存储 pid,获得 application name

v_replice_mode text 是复制模式,用于分区分是同步复制还是异步负责。i record 是没有固定格式的一条的数据。y int 用于临时自身的变量。

image.png

begin 创建触发器,可以在触发器里面写一些参数。这些参数不是在 function 里面指定,而是在创建触发器指定通过类似于 ca 的方法来获得的参数传递,不是直接在函数里面写的参数。

它的参数传递是 TG_ARGV的数组。比如从零开始零就是第一个参数。创建触发器时,可以在引号内部输入参数值。零号参数是指 foreign server 的名字,也就是触发器复制到 server 里的位置。

v_dst_server 连接名然后第二个参数是目标的 schema 的名字复制到远端服务器远端服务器对应的地方。

v_dst_table_name 是远端的表名。

防止死循环 v_application_name_check,application name 会在连接的时候用到。

同步模式的就是在创建触发器的时候,选择同步复制还是异步复制,同步复制触发器里面的逻辑是不一样的。接下来的话就是获得当前的 pid就是行记录触发的 pid,根据 pid,可以获得 application name。

如果是被远触发过来的链接,带有个 server 属性server 里面已经抄写 application。比如 server3.150上面连接到3.39,在3.39就能够看到application name,就叫AAABB。同样在3.39连到3.150也会到它配置的application name。

这里使用的 application name 来确保是远端触发器触发的连接。所以如果它等于提供application name,就可以不使用,不会触发无限的循环。

image.png

对于9.1以及以前的版本的话,字段叫 prcpid。把 application name 传到客户端cri 表示是客户端过来的application。然后 application name check 可能是在创建初期check name。检查跟客户端的一致,如果一致,表示是触发器触发的操作就不会进行循环。

如果是复制程序连上来的会话,如果它相等,返回空,直接返回。相因为连接是远端连,不是本地的操作。本地人工的操作的 application name 跟 cri 可能不一样就是当然如果自己也使用一致的 cri,也可以让它 return null, 只要等号两边匹配,就会 return null 防止死循环。

image.png

然后是生成一些组件的信息。组件的信息,是从约束里面来获取约束表里面就有组件一些信息,比如 tg rr id 是触发器的变量。如果要去看完整的触发器变量可以在触发器章节,看到它支持的变量。

image.png

是在 P2PQCQ里面有章节叫做 trigger里面的支持的一些变量。

image.png

这是在 POPQC 所写的触发器函数里支持的一些函数。比如 tg relid它对应的就是表的 object能够获取到它的 pk的值把长度取出来。长度就是 pk 的字段的个数。比如测试表是 pk1和 pk2,所以它取值2。

接下来获取 pk 的 vector 的信息,以及它的 attname 的数组。attname 的数据是从 attribute 里面去取。这里判断版本如果是九的版本,就比如9.0或者9.x,下面是8.x。

9.x要的是 dblink 的函数里面,要的是逻辑顺序,比如 note,它要的是逻辑顺序,真正输出的逻辑 code numbers。而以前的版本,它要的是物理顺序,物理顺序就来自 pg_attriute 表里面的个 attnumbers。所以这里有一定的区别。

image.png

比如取出来是九的版本,就用窗口函数把它的真正的逻辑顺序取出

然后如果是八的版本,直接取att 以及 attnumber把它转换成 int2ector然后另外一个就直接存在的聚合的里面就可以。

如果不是8和9的版本,直接就抛出异常。取完之后就要开始判断,如果当前的 operate,也就是当前的触发触发器的是 sql 语句,它是 insert 语句,要生成哪些东西如果是insert语句,就去从 new 里面使用 quote literal 函数相当于是把一些要存储的值封装起来也就是它会帮你做一些转移

比如 select quote literal<’\’>可能有一些需要转移的东西它有个反斜线符号,它会帮你转移。然后再去使用可以直接使用这种 quote literal 的,放在 quote literal execute diving in the execute 里面,就会出现遇到转移的支付报错的问题。所以封装一定使用 quote literal

相对于使用y去做判断。比如第一次是用一句动态 sql 语句直接创建数组,然后如果 pk 多个字段要往后面再来pad相当于做值交换,如果有三个字段不会有问题。只是交换之后,把整个的 pk 拼装成 array_appendto 数据。

上面是 insert接下来是 delete。

上面数组拼装完之后,使用 build_sql_insert生成远端执行的 sql 语句,sql 语句就存在 v_carry。v _query 就是调用 d bg execute 要去执行的 sql 语句。

接下来是 delete,如果是 delete,要用到 old。然后再使用 sql delete 去生v_carry。

如果触发 sql 是 update 语句,这里先去做 delete,也就是用 old 的去生成,然后再用 new 去生成 insert 语句。相当于是 update 用到 old 和 new。如果是 truncate 语句,直接 truncate table only 目标表就行。

然后就要把目标 schema 和目标表替换成现有的表名

image.png

比如目标的 schema 和目标的表名,本地表的表名以及 schema 不一样,要做替换操作。比如 local 表是 local.local test,然后 remote 的表是 remote.mtn test所以就有替换的操作

如果是updata相当于生成两个 v_query。v_query updata1, v_query updata2 ,一个 delete,一个 resert都要做replace 的操作,就是去查找目标表名,找到就直接替换成远端的 schema name 和 dst_table_name

对于 update,因为是两个 sql 语句,所以它们最终在远端执行的 v_dst_query 要合并,就是先执行 delete,然后执行 insert

否则如果不是 update,就直接替换

接下来就是去判断如果是异步复制的操作,首先是判断当前表有没有被锁。

image.png

也就是前面处理错误日志,有加锁过程。如果正在做远端,做 sql 操作的,对于 server 有操作的防止顺序错乱,就是事物的执行顺序错乱。只要处理 think error record,写入就直接返回

如果发现就继续往错误表里面写记录,而不是立刻去调用 dblink excute,能够确保事物的执行顺序的一致性。

然后第二个要判断的是 server 里面是否还有记录。在错误记录里面,目标 server 的复制,还有一些错误没有处理完,不能够直接去调用 dblink excute 去远端执行,也是为确保事物的执行顺序本地的事物执行顺序和远端的事物执行顺序的一致性。

如果上面判断都没有问题,就表示异步复制可以调用 dblink execute 去复制到远端。

接着判断链接是不是存在。如果不存在,就调用 dblink connect 去产生连接。然后连接完之后判断是同步复制还是异步复制。如果是同步复制,通过 dblink execute。excute 后面的参数是 true。表示如果远端执行失败,整个的触发器函数都会回滚本地的 DML 语句也会回滚。

如果是异步复制,这里就是 false,在远端执行失败的话没有关系远端执行失败,它会返回状态,状态是 error就往 sql 表里面插入一条记录,sql 语句 v_destination_query,是在远端执行失败的意思但是不会导致整个本地的事务的回滚,这就是异步复制。

上面是同步复制,如果远端执行失败,本地事务回滚。异步复制如果远端的 circle 记忆失败,本地不需要回

image.png

接下来就是异常的捕获,异常的捕获是捕获的任何的上面的一些异常,如果是异步复制往本地的表里面复制失败的记录然后抛出 notice,不是警告级。如果是同步复制,捕获到异常之后,就直接抛出错误。表示遇到任何错误,都直接本地回滚。

函数逻辑比较简单,但是比较庞大。

 

三、回顾

首先还是要在本地库里面,local 库里面再去创建触发器。触发器分为是 insert update 和 delete 的触发器,比如触发器里面的几个参数,目标 servere,是目标 schema 的名字,然后表名是 application name。现在用的是同步复制,也就是如果复制失败,它直接就会报错。在远端也是同样的去创建这两个触发器

就可以往本地的表里面去写入一些记录。比如在本地表里插入十条结果。在异地的表里面,也能够看到条记录。在远端同样也插入十条记录,然后本地也能看到。

image.png

看到它有报错不能够建立连接。说明150肯定限制。

防火墙上面有没有做限制防火墙没有限制。

看 pg_hba.copy 没有做配置也就是没有配置允许连接。

image.png

拒绝连接,也就是确实是问题。

直接把防火墙先关掉,

它这里监听,只监听本地端口。所以两个网络没有打通,去做测试网络首先得保证。

image.png

现在相当于是本地表里面已经有12条记录,相当于 multi-master 的复制完成

再更新。比如更新本地表的 pk ,把 pk 改成new。刷新后已经更新。

接下来在 remote 这里也去做更新。在remote这里把 pk2更新成 IT,去表里面去查,更新已经成功,就是双向的更新完成

删除是不是也能够正常的删除在远端去做删除,远端删除记录,剩两条记录,双向删除成功。

现在 updata delete insert 双向都可以复制。

最后来试turncate。在 local 里面 turncate 表,在远端表也已经 turncate。

上面是同步的复制。接下来是异步辅助。

image.png

只要重新创建个i think ink再把同步的触发器禁掉,比如在 local 库里面,创建是两个异步的触发器,异步触发器只要在个 server 参数里面指定 I think 之后,触发器逻辑会去判断。异步触发器的处理逻辑不一样。

image.png

注意在这里使用 aaa_bbb_digoal一定要server name 一致,和 for server 一致

image.png

aaa_bbb_digoal 是 dblink 连过来的。如果是通过连接过来触发的触发器,在逻辑判断里面,直接返回,不会再触发下个触发,规避死循环的过程。

接下来是在远端创建,两个同步触发器也已经创建。远端的触发器是基于 rmt test 的表。先去做正向同步,从 local导入到 rmt。插入一条记录,现在是异步的过程插入是正常

而在反向同步,在远端也插入。在远端插入完之后。在本地端能看到,insert 的同步正常。如果是在本地里写违反唯一约束的情况告诉你无法约束不会触发任何处罚性,同时它也不会去写同步错误

image.png

来做更新端做更新。更新完之后,看到词已经更新成 new,然后,远端也更新完成local 也更新成 new local。

错误的测试。比如连接失败,远端连接失败使用异步不会报错。它相当于是本地插入成功,但是会写到同步错误表里面。

image.png 

比如直接把数据库关掉提示远端连接失败,但是本地的插入已经成功。同时看到同步的错误记录里面就有失败的记录

然后再往里面插入记录都会报错误,只是它会帮你把它写到错误记录

接下来把数据库起来调用 deal_sync_err_rec 函数去同步记录

比如每次处理十条然后and could not execute select *from 错误

数据库已经起来。函数报 your unknown he could not execute 错误,远端去执行 insert 报错误。继续插入第13条记录。按照逻辑,因为 sql 表里面还有记录,所以它现在是不允许远端做任何复制。

去查 single area 表,应该有三条记录,本地有所有的记录。错误是因为刚刚连接导致的连接重启之后连接一直没有去重新建立

由于心跳机制导致

现在相当于是所有的错误全部处理完成,本地记录五条远端的记录已经处理掉,远端记录也正常。刚刚的错误因为连接造成的。

general trigger 函数,可以放在任意的表上,如果在实际使用场景当中有需要,只要有 db link,然后两个数据库网络相通同时有 PPCQ language,就可以实现两个数据库 two master 点对点的复制

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
存储 SQL 安全
【MySQL学习笔记】系列一:数据库概述、初识关系型数据库MySQL(二)
【MySQL学习笔记】系列一:数据库概述、初识关系型数据库MySQL(二)
10333 0
|
存储 SQL Oracle
【MySQL学习笔记】系列一:数据库概述、初识关系型数据库MySQL(一)
【MySQL学习笔记】系列一:数据库概述、初识关系型数据库MySQL(一)
|
SQL 关系型数据库 Linux
【PostgreSQL】入门学习笔记(包括安装、环境与参数配置、故障排查以及备份还原等)
以下内容为前几天在备考PostgreSQL入门考试时候做的笔记,经过了全职的两天的奋战与实验,并最终顺利通过了PCA初级认证考试。现在把我学习的笔记分享给大家,文中有对应的思维导图图片可供查看,内容与后面正文文本一致。另外,由于SQL语句部分比较基础,基本上会一门数据库就都会,所以此处部分省略掉不做过多记录了。
324 0
【PostgreSQL】入门学习笔记(包括安装、环境与参数配置、故障排查以及备份还原等)
|
SQL 移动开发 关系型数据库
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)|学习笔记
快速学习PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)
816 0
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)|学习笔记
|
存储 SQL 监控
PolarDB-X 进行 TP 负载测试(三)| 学习笔记
快速学习 PolarDB-X 进行 TP 负载测试。
322 0
PolarDB-X 进行 TP 负载测试(三)| 学习笔记
|
存储 运维 关系型数据库
PolarDB-X 读写分离与 HTAP| 学习笔记
快速学习 PolarDB-X 读写分离与 HTAP。
346 0
PolarDB-X 读写分离与 HTAP| 学习笔记
|
SQL 存储 运维
PolarDB-X 的部署与运维(三)| 学习笔记
快速学习 PolarDB-X 的部署与运维。
520 0
PolarDB-X 的部署与运维(三)| 学习笔记
|
数据可视化 Java 分布式数据库
PolarDB-X 数据 TTL 过期删除(三)| 学习笔记
快速学习 PolarDB-X 数据 TTL 过期删除。
163 0
PolarDB-X 数据 TTL 过期删除(三)| 学习笔记
|
运维 关系型数据库 测试技术
PolarDB-X 冷热数据归档(二)| 学习笔记
快速学习 PolarDB-X 冷热数据归档。
224 0
PolarDB-X 冷热数据归档(二)| 学习笔记
|
SQL 存储 Kubernetes
PolarDB-X 数据导入导出 | 学习笔记
快速学习 PolarDB-X 数据导入导出
688 0
PolarDB-X 数据导入导出 | 学习笔记

热门文章

最新文章