pgpool find primary node in master/slave stream replication mode

今天一位群里的兄弟遇到的pgpool的问题,

pgpool的后端是两个数据库, 分别是master和standby. (用stream replication搭建好的两个数据库).

pgpool 和主库放在同一个服务器上.

pgpool 的几个关键配置摘录一下 :

listen_addresses = '*'
port = 9999
socket_dir = '/tmp'
pcp_timeout = 1000
pcp_port = 9898
pcp_socket_dir = '/tmp'
backend_hostname0 = '127.0.0.1'
backend_port0 = 5433
backend_weight0 = 1
backend_data_directory0 = '/opt/PostgreSQL/9.1/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_hostname1 = '10.10.0.214'
backend_port1 = 5433
backend_weight1 = 1
backend_data_directory1 = '/opt/PostgreSQL/9.1/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
connection_cache = on
replication_mode = off
replicate_select = off
load_balance_mode = on
master_slave_mode = on
master_slave_sub_mode = 'stream'
sr_check_period = 0
sr_check_user = 'nobody'
sr_check_password = ''
delay_threshold = 0
parallel_mode = off

配置好后连接pgpool的9999端口, 创建表或者UPDATE报错 : 

postgres=> create table test(id int);
ERROR:  cannot execute CREATE TABLE in a read-only transaction

查看inet_server_addr()返回的是standby节点的IP. 也就是SQL发送到standby节点了.

排错 : 

pgpool找出primary节点是通过pg_is_in_recovery来的. 源码如下 : 

main.c

/*
 * Find the primary node (i.e. not standby node) and returns its node
 * id. If no primary node is found, returns -1.
 */
static int find_primary_node(void)
{
        BackendInfo *bkinfo;
        POOL_CONNECTION_POOL_SLOT *s;
        POOL_CONNECTION *con;
        POOL_STATUS status;
        POOL_SELECT_RESULT *res;
        bool is_standby;
        int i;

        /* Streaming replication mode? */
        if (pool_config->master_slave_mode == 0 ||
                strcmp(pool_config->master_slave_sub_mode, MODE_STREAMREP))
        {
                /* No point to look for primary node if not in streaming
                 * replication mode.
                 */
                pool_debug("find_primary_node: not in streaming replication mode");
                return -1;
        }

        for(i=0;i<NUM_BACKENDS;i++)
        {
                if (!VALID_BACKEND(i))
                        continue;

                /*
                 * Check to see if this is a standby node or not.
                 */
                is_standby = false;

                bkinfo = pool_get_node_info(i);
                s = make_persistent_db_connection(bkinfo->backend_hostname,
                                                                                  bkinfo->backend_port,
                                                                                  "postgres",
                                                                                  pool_config->sr_check_user,
                                                                                  pool_config->sr_check_password, true);
                if (!s)
                {
                        pool_error("find_primary_node: make_persistent_connection failed");
                        return -1;
                }
                con = s->con;
#ifdef NOT_USED
                status = do_query(con, "SELECT count(*) FROM pg_catalog.pg_proc AS p WHERE p.proname = 'pgpool_walrecrunning'",
                                                  &res, PROTO_MAJOR_V3);
                if (res->numrows <= 0)
                {
                        pool_log("find_primary_node: do_query returns no rows");
                }
                if (res->data[0] == NULL)
                {
                        pool_log("find_primary_node: do_query returns no data");
                }
                if (res->nullflags[0] == -1)
                {
                        pool_log("find_primary_node: do_query returns NULL");
                }
                if (res->data[0] && !strcmp(res->data[0], "0"))
                {
                        pool_log("find_primary_node: pgpool_walrecrunning does not exist");
                        free_select_result(res);
                        discard_persistent_db_connection(s);
                        return -1;
                }
#endif
                status = do_query(con, "SELECT pg_is_in_recovery()",
                                                  &res, PROTO_MAJOR_V3);
                if (res->numrows <= 0)
                {
                        pool_log("find_primary_node: do_query returns no rows");
                }
                if (res->data[0] == NULL)
                {
                        pool_log("find_primary_node: do_query returns no data");
                }
                if (res->nullflags[0] == -1)
                {
                        pool_log("find_primary_node: do_query returns NULL");
                }
                if (res->data[0] && !strcmp(res->data[0], "t"))
                {
                        is_standby = true;
                }
                free_select_result(res);
                discard_persistent_db_connection(s);

                /*
                 * If this is a standby, we continue to look for primary node.
                 */
                if (is_standby)
                {
                        pool_debug("find_primary_node: %d node is standby", i);
                }
                else
                {
                        break;
                }
        }

        if (i == NUM_BACKENDS)
        {
                pool_debug("find_primary_node: no primary node found");
                return -1;
        }

        pool_log("find_primary_node: primary node id is %d", i);
        return i;
}

因为需要连到backend host 上去执行SQL, 所以需要在pgpool.conf中配置用户密码.

因此直接连接到primary 节点创建一个普通用户,

psql -h 127.0.0.1 -p 5433
create role nobody nosuperuser login encrypted password '123456';

然后确认pg_hba.conf允许连接, 如果没有则添加条目, reload数据库.

配置pgpool.conf,

sr_check_period = 10
sr_check_user = 'nobody'
sr_check_password = '123456'

重启pgpool. 

pgpool -m fast stop
pgpool -f ./pgpool.conf -c

再测就没问题了.

使用pgbench压力测试, 查询语句将分布到两个节点.

时间: 2024-10-29 11:56:42

pgpool find primary node in master/slave stream replication mode的相关文章

PGPool-II master/slave mode using caveat

PGPool-II的master/slave模式类似load balance模式.只不过master/slave是与PGPool-II以外的第三方复制软件结合使用的.(如当前支持的slony和stream replication) PGPool会将需要复制的SQL发到Master数据库,不需要复制的SQL符合条件的情况下将可能被分发到Slave数据库以达到负载均衡的效果. 以下是Master/Slave mode使用注意事项: 1. 临时表的DDL,DML操作必须在Master库完成(PGPoo

redis 学习笔记(3)-master/slave(主/从模式)

类似mysql的master-slave模式一样,redis的master-slave可以提升系统的可用性,master节点写入cache后,会自动同步到slave上. 环境: master node: 10.6.144.155:7030 slave node: 10.6.144.156:7031   一.配置 仅需要在slave node上修改配置: 找到slaveof这行,参考下面的修改(填上master node的Ip和端口就完事了) slaveof 10.6.144.155 7030 另

教你如何在Windows下搭建MySQL Master Slave

一.背景 服务器上放了很多MySQL数据库,为了安全,现在需要做Master/Slave方案,因为操作系统是Window的,所以没有办法使用keepalived这个HA工具,但是我们可以接受人工进行切换,有什么好的方案呢? 二.几种Master/Slave逻辑架构图 (Figure1:单Master-单Slave) (Figure2:单Master-多Slave) (Figure3:单Master-级联Slave) (Figure4:Master/Slave部署逻辑图)

mysql(master/slave)主从复制原理及配置图文详解_Mysql

1 复制概述       Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的.复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环.这些日志可以记录发送到从服务器的更新.当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置.

34.5. Master / Slave

34.5.1. master /etc/named.conf # cat /etc/named.conf zone "example.com" { type master; file "/var/named/example.com.zone"; allow-transfer { 172.16.1.23; 120.100.100.23; }; }; notify 指令会自动通知所有这个域的所有在ns记录上的机器,also-notify指令可以用来通知所有不在ns记录上

PostgreSQL HOT STANDBY using Stream replication

案例解析二.PostgreSQL HOT STANDBY by stream replication 测试:一.准备硬件1. 主节点硬件配置DISK : 146GB*6MEM : 14GBCPU : 2.83GHz*82. standby节点硬件配置DISK : 146GB*4MEM : 8GBCPU : 2.0GHz*8 二.准备环境1. 系统Red Hat Enterprise Linux Server release 5.5 (Tikanga) x642. 时钟同步8 * * * * /u

Oracle Stream Replication技术简介

Stream 是Oracle 的消息队列(也叫Oracle Advanced Queue)技术的一种扩展应用. Oracle 的消息队列是通过发布/订阅的方式来解决事件管理.流复制(Stream replication)只是基于它的一个数据共享技术,也可以被用作一个可灵活定制的高可用性方案. 它可以实现两个数据库之间数据库级,schema级,Table级的数据同步,并且这种同步可以是双向的. Oracle Stream也是通过数据冗余来提高可用性,这一点和Data Guard 类型. Oracl

MYSQL的master/slave数据同步配置的例子

我的测试环境.基本上数据是瞬间同步,希望对大家有帮助 redhat 9.0 mysql3.23.57 mysql数据同步备份 A服务器: 192.168.1.2 主服务器master B服务器: 192.168.1.3 副服务器slave A服务器设置 #mysql –u root –p mysql>GRANT FILE ON *.* TO backup@192.168.1.3 IDENTIFIED BY '1234'; mysql>\exit 上面是Master开放一个账号backup密码1

基于MySQL Master Slave同步配置的操作详解_Mysql

环境:PC:ubuntu 10.10  192.168.1.112(master) 192.168.10.245(slave) MySQL : 5.1.49-1ubuntu8.1-log在master中已经存在数据库test 首先修改mysql配置文件:/etc/mysql/my.cnf[master]#author:zhxia 复制代码 代码如下:  #master 同步设置 server-id               = 1 log_bin                 = /var/