Can session_replication_role used like MySQL's BlackHole Engine?

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:
  测试版本PostgreSQL 9.0.2
    PostgreSQL数据库自带的流复制带来了非常强大的数据库容灾和负载均衡等特性体验。它告诉我们什么是TMD惊喜。预知惊喜请翻阅我以前写的两篇博客 
http://blog.163.com/digoal@126/blog/static/16387704020110442050808/
http://blog.163.com/digoal@126/blog/static/1638770402010113053825671/
    不过还是有点不完美,例如不能控制哪些表是需要复制的哪些表是不需要复制的。
    在MySQL中有一种存储引擎叫做黑洞存储引擎,配置为黑洞存储引擎的表对他做DML时啥都不做,但是可以在SLAVE端配置这个表为非黑洞引擎,那么这些DML在SLAVE端将被执行,并有作用。
    在PostgreSQL中有一个叫session_replication_role的参数,根据参数的解释: 
  session_replication_role (enum)
Controls firing of replication-related triggers and rules for  the         current session.  

Setting this variable requires          superuser privilege and results in discarding any previously cached          query plans.  

Possible values are origin (the default),         replica and local.         

See ALTER TABLE for         more information. 

    在ALTER TABLE中也有一段这样的语法:    
   DISABLE TRIGGER [ trigger_name | ALL | USER ]
    ENABLE TRIGGER [ trigger_name | ALL | USER ]
    ENABLE REPLICA TRIGGER trigger_name
    ENABLE ALWAYS TRIGGER trigger_name
    DISABLE RULE rewrite_rule_name
    ENABLE RULE rewrite_rule_name
    ENABLE REPLICA RULE rewrite_rule_name
    ENABLE ALWAYS RULE rewrite_rule_name


从而可以根据当前SESSION的角色属性来控制rule和trigger是否生效。那么是否可以利用这个特性来控制哪些表可以被复制,哪些表不能被
复制呢?(如创建DO INSTEAD NOTHING的rule或触发器),欲知结果,请看如下测试:
    1. 测试一 : 主库session_replication_role=origin  hot_standby session_replication_role=replica
主库 :
digoal=> show session_replication_role;
 session_replication_role 
--------------------------
 origin
(1 row)
digoal=> select count(*) from tbl_user;
 count 
-------
    25
(1 row)

备库 :
digoal=> show session_replication_role;
 session_replication_role 
--------------------------
 replica
(1 row)
digoal=> select count(*) from tbl_user;
  count 
 -------
     25
 (1 row)

主库 : 
新建insert do nothing的触发器,
CREATE OR REPLACE FUNCTION digoal.f_user_insert_replica()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$ begin return old; end;
$function$
create trigger t_user_insert_replica before insert on tbl_user for each row execute procedure f_user_insert_replica();
digoal=> \d+ tbl_user

默认情况下是这样的,在origin或local模式role模式生效,
Triggers:
    t_user_insert_replica BEFORE INSERT ON tbl_user FOR EACH ROW EXECUTE PROCEDURE f_user_insert_replica()

现在的目标是让他在replica模式生效,因此
digoal=> alter table tbl_user disable trigger t_user_insert_replica ;
ALTER TABLE
digoal=> alter table tbl_user enable replica trigger t_user_insert_replica ;
ALTER TABLE
digoal=> \d+ tbl_user (已经改变为仅仅replica模式被触发)
Triggers firing on replica only:
    t_user_insert_replica BEFORE INSERT ON tbl_user FOR EACH ROW EXECUTE PROCEDURE f_user_insert_replica()

现在开始测试插入操作:
digoal=> insert into digoal.tbl_user values (1,'zhou','digoal','sky-mobi');
INSERT 0 1
digoal=> select count(*) from digoal.tbl_user;
 count 
-------
    26
(1 row)

很明显,主库因为在origin模式所以没有触发这个触发器.记录已经插入.
下面看看hot_standby的情况:
digoal=> select count(*) from tbl_user;
 count 
-------
    26
(1 row)

很明显hot_standby也没有触发这个触发器。记录与主库一致。
把触发器改为origin和local触发模式,验证触发器有效性,
主库:
digoal=> alter table tbl_user enable trigger t_user_insert_replica ;
ALTER TABLE
\d+ tbl_user
Triggers:
    t_user_insert_replica BEFORE INSERT ON tbl_user FOR EACH ROW EXECUTE PROCEDURE f_user_insert_replica()
digoal=> insert into digoal.tbl_user values (1,'zhou','digoal','sky-mobi');
INSERT 0 0

触发器有效
digoal=> select count(*) from digoal.tbl_user;
 count 
-------
    26
(1 row)

hot_standby数据库:
digoal=> select count(*) from digoal.tbl_user;
 count 
-------
    26
(1 row)

# 换成for each statement结果一样.

2. 测试二 : 看看规则行不行
主库:
首先删除触发器
digoal=> drop trigger t_user_insert_replica on tbl_user;
创建规则
digoal=> create or replace rule r_tbl_user_insert_replica as ON  insert to tbl_user do instead nothing;
digoal=> alter table tbl_user  disable rule r_tbl_user_insert_replica ;
ALTER TABLE
digoal=> alter table tbl_user enable replica rule r_tbl_user_insert_replica ;
ALTER TABLE
Rules firing on replica only:
    r_tbl_user_insert_replica AS
    ON INSERT TO tbl_user DO INSTEAD NOTHING
digoal=> select count(*) from digoal.tbl_user;
 count 
-------
    26
(1 row)
digoal=> insert into digoal.tbl_user values (1,'zhou','digoal','sky-mobi');
INSERT 0 1
digoal=> select count(*) from digoal.tbl_user;
 count 
-------
    27
(1 row)

hot_standby库(很明显又没有起到作用):
digoal=> select count(*) from tbl_user;
 count 
-------
    27
(1 row)

主库:(测试RULE有效性)
digoal=> set session_replication_role=replica;
digoal=> insert into digoal.tbl_user values (1,'zhou','digoal','sky-mobi');
INSERT 0 0
digoal=> select count(*) from digoal.tbl_user;
 count 
-------
    27
(1 row)


3. 测试三 : 修改session_replication_role
Primary和Slave连接使用walsender和walreceiver进程,那么会不会是slave连接到主库的模式决定了触发器或规则的触发条件呢?
修改主库的模式 :
vi postgresql.conf
session_replication_role=replica

重启主库和hot_standby数据库.
重新以上的测试,还是没有达到预期效果.

4. 测试四 : 修改recovery.conf
那么会不会是需要在recovery.conf中配置呢?
修改hot_standby数据库的recovery.conf配置:
primary_conninfo = 'host=172.16.3.33 port=1921 user=repuser1 keepalives_idle=60 options="session_replication_role=replica"'

修改后重启hot_standby数据库,报错,说明还是行不通
postgresql-2011-02-09_105814.csv:2011-02-09 10:58:19.593 CST,,,16375,,4d5202cb.3ff7,1,,2011-02-09 10:58:19 CST,,0,FATAL,XX000,"could not connect to the primary server: invalid connection option ""session_replication_role""

5. 测试五 : 非stream模式
注释掉hot_standby 数据库的配置文件recovery.conf中的primary_conninfo参数
重启hot_standby数据库,
在主库测试:
digoal=# set session session_replication_replica=replica;
digoal=# insert into digoal.tbl_user select * from digoal.tbl_user;
INSERT 0 0
digoal=# set session session_replication_replica=origin;
digoal=# insert into digoal.tbl_user select * from digoal.tbl_user;
INSERT 0 27
...
digoal=# insert into digoal.tbl_user select * from digoal.tbl_user;
INSERT 0 221184
digoal=# checkpoint;
CHECKPOINT
digoal=# select * from pg_switch_xlog();
 pg_switch_xlog 
----------------
 4/F6536390
(1 row)

digoal=# checkpoint;
CHECKPOINT

等待hot_standby数据库应用XLOG后,查看
digoal=> select count(*) from digoal.tbl_user;
 count  
--------
 442368
(1 row)

stream和log shipping模式下得到的结果一样,

6. 测试六 : 
开启hot_standby的DEBUG信息
debug_print_parse = on
debug_print_rewritten = on
debug_print_plan = on
debug_pretty_print = on
log_parser_stats = on
log_planner_stats = on
log_executor_stats = on

在复制过程中,到hot_standby的日志中看不到相关的DEBUG信息,说明复制过程没有发生parse,rewritten,plan.executor这些事件.
 参考 PostgreSQL manual 章节: Overview of PostgreSQL Internals , rule和trigger在复制时没有被触发与复制的机制和rule,trigger在数据库的执行阶段有直接关系.
  参考 源代码部分/src/backend/replication

目前想要在PostgreSQL 9.0.2 日志级复制环境中控制哪个表需要被复制,哪个表不需要被复制,使用session_replication_role和触发器或rule模式配合是行不通的。
当然在pgpool这类SQL级的复制中是可以行得通的.
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL LIKE 子句
总结 vue3 的一些知识点:MySQL LIKE 子句
|
4月前
|
SQL 关系型数据库 MySQL
MySQL LIKE 子句
MySQL LIKE 子句
|
5月前
|
Oracle 关系型数据库 MySQL
MySQL复制表结构create table as与like的区别
MySQL复制表结构create table as与like的区别
|
4月前
|
关系型数据库 MySQL Java
Elasticsearch 类比 mysql 实现 in and like or(Spring-Data-Elasticsearch)
Elasticsearch 类比 mysql 实现 in and like or(Spring-Data-Elasticsearch)
46 0
|
2月前
|
SQL 关系型数据库 MySQL
like concat 兼容h2、mysql、pgsql语法
like concat 兼容h2、mysql、pgsql语法
34 0
|
2月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL LIKE 子句
总结 vue3 的一些知识点:MySQL LIKE 子句
|
3月前
|
自然语言处理 搜索推荐 关系型数据库
Elasticsearch实现Mysql的Like效果
在Mysql数据库中,模糊搜索通常使用LIKE关键字。然而,随着数据量的不断增加,Mysql在处理模糊搜索时可能面临性能瓶颈。因此,引入Elasticsearch作为搜索引擎,以提高搜索性能和用户体验成为一种合理的选择。
Elasticsearch实现Mysql的Like效果
|
3月前
|
关系型数据库 MySQL Unix
MySQL LIKE 子句
【1月更文挑战第5天】MySQL 使用讲解 第05期
|
4月前
|
SQL 前端开发 关系型数据库
MYSQL基础知识之【LIKE子句的使用 ,NULL值的处理,空值的处理】
MYSQL基础知识之【LIKE子句的使用 ,NULL值的处理,空值的处理】
59 0
|
5月前
|
关系型数据库 MySQL 测试技术
软件测试|MySQL LIKE:深入了解模糊查询
软件测试|MySQL LIKE:深入了解模糊查询
43 0