PostgreSQL 多数据库集簇配置及多数据库复制方法【流程+代码实例】

PostgreSQL 多数据库集簇配置及多数据库复制方法

1. 多数据库集簇配置

安装下载完postgresql后,系统此时包含一个postgres用户和一个名为postgres的默认数据库。

PostgreSQL 基本命令

  • 服务管理命令

    bash 复制代码
    # 停止和启动及重启PostgreSQL服务
    sudo systemctl stop postgresql
    sudo systemctl start postgresql
    sudo systemctl restart postgresql
    
    # 查看服务当前状态
    sudo systemctl status postgresql
    
    # 设置服务开机自启动
    sudo systemctl enable postgresql
    # 禁止服务开机自启动
    sudo systemctl disable postgresql

    systemctl 是 Linux 系统中用于管理系统服务的工具

  • 客服端交互命令

    bash 复制代码
    # 连接到数据库
    sudo -u postgres psql
    
    # 连接指定数据库
    sudo -u postgres psql -d <database_name>
    
    # 退出
    \q
  • 数据库操作命令(psql客户端)

    sql 复制代码
    # 创建新数据库
    CREATE DATABASE <database_name>;
    
    # 删除
    DROP DATABASE <database_name>;
    
    # 列出
    \l
    
    # 切换
    \c <database_name>
  • 用户及权限管理

    sql 复制代码
    # 创建
    CREATE USER your_username WITH PASSWORD 'your_password';
    
    # 删除
    DROP USER your_username;
    
    # 授权
    GRANT ALL PRIVILEGES ON DATABASE your_database_name TO your_username;
    
    # 撤销
    REVOKE ALL PRIVILEGES ON DATABASE your_database_name FROM your_username;

自定义端口与数据库集簇

配置要设置端口等基本信息,需要先停止服务

bash 复制代码
sudo systemctl stop postgresql

初始化集簇步骤:

bash 复制代码
# 创建一个数据库集簇的数据目录 -p 递归创建
sudo mkdir -p /data/postgresql
# 赋权
sudo chown postgres:postgres /data/postgresql
# 当前用户使用postgres用户的身份初始化数据库集簇 -u 指定用户 -D 指定数据目录 -E 指定默认字符编码
sudo -u postgres /usr/lib/postgresql/<version>/bin/initdb -D /data/postgresql -E UTF8

initdb 是 PostgreSQL 数据库管理系统中的一个关键命令,主要用于初始化一个新的数据库集簇

修改配置文件:

bash 复制代码
sudo -u postgres vim <PG_HOME>/postgresql.conf
# 本例中<PG_HOME>为 /data/postgresql 即数据目录

# 设置值
listen_addresses = '*'   # 允许远程访问
port = 5439    # 改成任意空闲端口          
max_connections = 100 # 设置最大连接数

等价于:

bash 复制代码
# -a 追加模式 tee 将标准输入复制到每个指定的文件
sudo -u postgres tee -a <PG_HOME>/postgresql.conf << EOF
listen_addresses = '*'   
port = 5439            
max_connections = 100   
EOF

EOF(Here Document)是一种在脚本中向文件追加内容或传递多行输入的便捷方法。

两种启动数据库集簇方式

1.手动
bash 复制代码
# pg_ctl 根据-D 后的数据目录来定位要启动的数据库集簇。
sudo -u postgres /usr/lib/postgresql/<PostgreSQL-Version>/bin/pg_ctl start -D /data/postgresql

pg_ctl 是 PostgreSQL 提供的一个实用工具,用于控制 PostgreSQL 服务器的启动、停止、重启、重新加载配置等操作。

注意和systemctl的比较:

  • pg_ctl 是 PostgreSQL 自带的命令行工具,主要用于对 PostgreSQL 数据库集簇进行精细的控制和管理。直接与 PostgreSQL 服务器进行交互,操作的核心是数据库集簇。
  • systemctl 是 Linux 系统中 systemd 系统和服务管理器的命令行工具,用于管理系统服务。它是操作系统层面的服务管理工具,对各种系统服务(包括 PostgreSQL 服务)进行统一管理。(见2)

2.一键启动

首先创建Systemd服务文件

bash 复制代码
sudo vim /etc/systemd/system/postgresql-custom.service
# postgresql-custom 自定义名称,一个名称对应与一个数据库集簇

加入以下内容:

bash 复制代码
[Unit]
Description=PostgreSQL Custom Instance  # 对该服务的简要描述,方便用户了解服务的功能
After=network.target   # 确保在网络服务启动后再启动 PostgreSQL 服务

[Service]
Type=forking  # 服务使用 fork() 方式启动,即父进程启动子进程后退出
User=postgres
Group=postgres # 指定服务以 postgres 用户和 postgres 用户组的身份运行
Restart=on-failure  # 服务因异常退出时,systemd 会自动尝试重启该服务
ExecStart=/usr/lib/postgresql/14/bin/pg_ctl start -D /data/postgresql  # 启动服务时执行的命令
ExecStop=/usr/lib/postgresql/14/bin/pg_ctl stop -D /data/postgresql    # 停止服务时执行的命令

[Install]
WantedBy=multi-user.target  # 该服务在多用户模式下被启动

保存退出,命令行输入:

bash 复制代码
sudo systemctl daemon-reload   # 重新加载 systemd 配置
sudo systemctl start postgresql-custom # 若启动其他集簇,编辑对应systemd文件并启动即可

监听服务状态

bash 复制代码
# 监听的端口号; ss 显示套接字统计信息的工具 -t tcp -u udp -l 显示处于监听状态的套接字 -n 数字形式显示地址和端口号 -p 显示使用该套接字的进程信息  | grep <port_id>  筛选出监听 5439 端口的套接字信息
sudo ss -tulnp | grep 5439

对应端口显示listen 即可。

2. 多数据库异步流复制

速通Docker安装

  • 更换apt源

    bash 复制代码
     sudo apt update
     sudo apt install apt-transport-https \
     ca-certificates \
     curl \
     software-properties-common \
                        gnupg \
                        lsb-release
     # **阿里源**
     curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg \
            | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
        # 添加 apt 源:
        # 阿里 apt 源
    echo "deb [arch=$(dpkg --print-architecture) \
    signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
    https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
    $(lsb_release -cs) stable" \
    | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    sudo apt update
    sudo apt-get update

    问题总结:

    1. sudo apt update 报错E: 仓库 "https://apt.postgresql.org/pub/repos/apt xenial-pgdg Release" 没有 Release 文件

    解决:sudo rm /etc/apt/sources.list.d/pgdg.list
    2. 安装curl依赖报错: curl : 依赖: libcurl3-gnutls (= 7.47.0-1ubuntu2) 但是 7.47.0-1ubuntu2.15 正要被安装

    解决:强制安装指定版本:sudo apt-get install libcurl3-gnutls=7.47.0-1ubuntu2

  • 安装Docker Engine

    插件先不装

    bash 复制代码
     sudo apt-get install docker-ce \
                    docker-ce-cli \
                    containerd.io 
  • 更换镜像

    bash 复制代码
    # 设置registry mirror
    sudo vim /etc/docker/daemon.json
    
    # 加入以下内容 (最新镜像源 可以网上找资源)
    {
        "registry-mirrors": [
            "https://docker.1ms.run",
            "https://docker.xuanyuan.me"
        ]
    }
    
    ## 重启Docker
    systemctl daemon-reload
    systemctl restart docker
  • 测试

    bash 复制代码
    sudo docker run hello-world
    # 本地找不到镜像就会去镜像源拉去相关镜像 输出对应镜像信息

异步流复制

动机

简单来说就是为了防止大哥出事,搞几个备份顺便还能分担大哥的压力。

准备工作

下载pg的docker镜像:

bash 复制代码
docker pull postgres

挂载数据卷同步数据:

bash 复制代码
ocker volume create postgre-data
创建主库容器
bash 复制代码
docker run -id --name=pg1 -v postgre-data:/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_PASSWORD=123456 -e LANG=C.UTF-8 postgres
# dock run :基于指定的镜像创建并启动一个新的容器
# -d 保持后台运行 -i 保持标准输入流处于打开状态 --name 命名
# -v 挂载数据卷 -v <column_name>:<data_path> 数据卷名称及容器内数据目录
# -p <home_port>:<container_port> 将容器内部的端口映射到宿主机的端口 能通过宿主机的 5432 端口访问容器内运行的 PostgreSQL 服务
# postgres 镜像名称
相关配置(挂载数据卷内配置,不进入容器)

获取主机ip

bash 复制代码
hostname  # 主机名
hostname -i # 主机ip

打开配置文件,加入配置信息

bash 复制代码
vim /var/lib/docker/volumes/postgre-data/_data/postgresql.conf

# 添加信息 普通模式 G 跳转底部
wal_level = replica         
max_wal_senders = 3        
hot_standby = on  
# host replication all 127.0.0.1/32 md5

# pg_hba.conf 文件定义了哪些客户端可以连接到 PostgreSQL 服务器,以及它们使用何种认证方法进行身份验证。
sudo vim /var/lib/postgresql/data/pg_hba.conf
#添加
host replication all 127.0.0.1/16 md5
# 退出重启容器 docker ps -a 查看容器状态
sudo docker restart pg1

在主库中插入测试数据:

bash 复制代码
# 进入容器并使用 psql 连接数据库
docker exec -it pg1 psql -U postgres
sql 复制代码
-- 创建学生表
CREATE TABLE students (
 student_id SERIAL PRIMARY KEY,
 name VARCHAR(100) NOT NULL,
 age INT,
 gender CHAR(1),
 enrollment_date DATE
 );-- 插入示例数据
INSERT INTO students (name, age, gender, enrollment_date)
 VALUES 
('张三', 20, 'M', '2024-09-01'),
 ('李四', 21, 'F', '2023-09-01'),
 ('王五', 22, 'M', '2022-09-01'),
 ('赵六', 19, 'F', '2025-01-15'),
 ('孙七', 23, 'M', '2022-03-20'),
 ('周八', 20, 'F', '2024-07-10'),
 ('吴九', 22, 'M', '2023-11-05'),
 ('郑十', 21, 'F', '2024-04-25'),
 ('王十一', 18, 'M', '2025-02-01'),
 ('李十二', 24, 'F', '2021-09-30'),
 ('张十三', 20, 'M', '2024-09-12'),
 ('刘十四', 22, 'F', '2023-06-18'),
 ('陈十五', 19, 'M', '2025-03-08');
 
 # \q 退出psql
创建备库(pg_basebackup 初始化)

创建备库

bash 复制代码
sudo docker run -d --name pg2 -e POSTGRES_PASSWORD=123456 postgres:latest bash -c "while true; do sleep 1; done" 
# PostgreSQL 需要一个数据目录来存储数据库文件。如果没有挂载数据卷,PostgreSQL 服务将无法启动,因为默认的数据目录是空的。
# 当 PostgreSQL 服务无法启动时,容器会因为没有主进程而退出 无限循环脚本阻止容器退出
# bash -c:在容器内启动一个 Bash Shell,并执行后面的命令

查看pg1ip:

bash 复制代码
sudo docker exec -it pg1

apt-get update
apt-get install net-tools
ifconfig

exit

执行pg_basebackup创建基础备份:

bash 复制代码
# -h 主库ip或主机名  -U 连接到主库使用的用户名 -D 基础备份数据存储的目标目录  -R 自动生成恢复配置文件 备库在启动时连接到主库,并开始接收 WAL(预写式日志)流,从而实现流复制。 -X 指定如何处理WAL  stream 通过流复制的方式实时获取主节点的 WAL 日志,确保备份数据的一致性。
sudo docker exec pg2 pg_basebackup -h <pg1_ip> -U postgres -D /var/lib/postgresql/data -P -R -X stream -v
# 172.17.0.2

pg_basebackup 是 PostgreSQL 提供的一个工具,用于创建 PostgreSQL 数据库集群的基础备份。基础备份是创建流复制环境的第一步,它会复制主节点上的所有数据文件,为从节点提供一个初始的数据副本。

启动备库:

bash 复制代码
sudo docker exec pg2 su postgres -c "pg_ctl start -D /var/lib/postgresql/data"

主备一致性

接下来就是验收结果

  • 主库检查

    sql 复制代码
    # 进入主库容器 psql进入pg交互
    SELECT client_addr, state, sync_state, sent_lsn, write_lsn  FROM pg_stat_replication;
    # 输出应备库IP等信息
  • 备库检查

    sql 复制代码
    # 备库同理
    SELECT pg_is_in_recovery(); # t 备库模式
    SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn() # 与主库一致
  • 数据一致性

    sql 复制代码
    # 主库写入
    CREATE TABLE test (id SERIAL PRIMARY KEY, data TEXT);
    INSERT INTO test (data) VALUES ('HA test');
    
    # 备库查询
    SELECT * FROM test;  # 数据一致
  • 日志信息等

相关推荐
李长渊哦20 分钟前
引入其他 YML 配置源 —— Spring Boot 中的 `import` 功能
数据库·spring boot·后端
try again!30 分钟前
个性化音乐推荐系统
android·数据库·sqlite
安 当 加 密1 小时前
TDE透明加密:免改造实现SQLServer数据库安全存储
数据库·sqlserver
fmdpenny2 小时前
Django创建数据库表失败处理方法
数据库·python·django
BirdMan982 小时前
Flask中实现对User模型的增删改查,并通过Flask-Alchemy与MySQL数据库交互
数据库·mysql·flask
isolusion3 小时前
Redis 主从复制详解:实现高可用与数据备份
数据库·redis·缓存
极客先躯4 小时前
高级java每日一道面试题-2025年2月18日-数据库篇-MySQL 如何做到高可用方案?
java·数据库·mysql·架构·高可用
我要升天!4 小时前
Linux中基础开发工具详细介绍
linux·运维·服务器·c++·postgresql
墨香染城城4 小时前
Mmybatis xml 连接数据库的方法
xml·数据库