1. 环境搭建
本文介绍了如何在同一台机器上使用 Docker 容器搭建 PostgreSQL 的主从同步环境。通过创建互联网络和配置主库及从库,详细讲解了数据库初始化、角色创建、数据同步和验证步骤。主要步骤包括设置主库的连接信息、创建用于复制的角色、使用 pg_basebackup 同步数据,并最终验证同步状态。
1.1. 主库搭建
# 创建docker容器互联网络
docker network create pg-network# 创建映射目录
mkdir /data/postgresdocker run -d -p 5500:5432 -v /docker-data/pgmaster:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=postgress@123 \
--name pgmaster --network=pg-network postgres:16.4
1.2. 从库搭建
# 创建从库
docker run -d -p 5501:5432 \
-e POSTGRES_PASSWORD=postgress@123 \
--name pgslave1 --network=pg-network postgres:16.4
1.3. 查看主库和从库 IP
# 查看容器IP pgmaster = 172.18.0.2
docker inspect pgmapgmaster = 172.18.0.2ster | grep IPAddress
# pgslave1 = 172.18.0.3
docker inspect pgslave1 | grep IPAddress
1.4. 主库配置
设置主服务的连接信息, 从库使用pg_basebackup
同步过来数据后可以直接使用这个配置去同步数据
# 追加参数 主服务的连接信息, 用于从属服务器读取使用
# SQL用户名和密码 user=repl password=repl
cat >> /docker-data/pgmaster/postgresql.conf <<- 'EOF'
primary_conninfo = 'host=172.18.0.2 port=5432 user=repl password=repl'
EOF
host=172.18.0.2
主库 IP , 这里因为使用了 同一个网络 pg-network, 所以可以直接通信user=repl password=repl
主库数据库中用于同步数据的角色和密码, 等下需要创建
设置只允许哪几个 IP 个角色可以复制数据
# 追加参数, 表示只允许这几个IP的角色repl复制数据
cat >> /docker-data/pgmaster/pg_hba.conf <<- 'EOF'
host replication repl 172.18.0.2/32 md5
host replication repl 172.18.0.3/32 md5
EOF
主库创建用于复制的角色
# 设置账户
docker exec -it pgmaster /bin/bash# 登录
pgsql -U postgres# 关闭异步提交
SET synchronous_commit = off;# 创建 角色名 = repl , 密码 = repl 的账户, 权限为登录和复制
create role repl login replication encrypted password 'repl';# 查看是否创建成功
\du# 退出
\q# ctrl + D 也可以退出
# 重启容器
docker restart pgmaster
# 追加参数 主服务的连接信息, 用于从属服务器读取使用
# SQL用户名和密码 user=repl password=repl
cat >> /docker-data/pgmaster/postgresql.conf <<- 'EOF'
primary_conninfo = 'host=172.18.0.2 port=5432 user=repl password=repl'
EOF# 追加参数, 表示只允许这几个IP的角色repl复制数据
cat >> /docker-data/pgmaster/pg_hba.conf <<- 'EOF'
host replication repl 172.18.0.2/32 md5
host replication repl 172.18.0.3/32 md5
EOF# 设置账户
docker exec -it pgmaster /bin/bash# 登录
pgsql -U postgres
# 关闭异步提交
SET synchronous_commit = off;# 创建 角色名 = repl , 密码 = repl 的账户, 权限为登录和复制
create role repl login replication encrypted password 'repl';# 查看是否创建成功
\du# 退出
\q# ctrl + D 也可以退出
# 重启容器
docker restart pgmaster
1.5. 拷贝主库数据
进入从属容器内部, 使用pg_basebackup 同步主库的数据到从库
# 进入从属容器
docker exec -it pgslave1 /bin/bash
# 同步主服务器数据, 注意 这里的 /docker-data/opt/postgresql-16.0/data 是容器内部的数据
pg_basebackup -Fp --progress -D /docker-data/opt/postgresql-16.0/data/ -R -h 172.18.0.2 -p 5432 -U repl --password
在本地创建目录, 将容器的数据拷贝出来
# 创建目录
mkdir -p /docker-data/opt/postgresql/pgslave1
# 将容器内部的数据复制到外部
docker cp pgslave1:/docker-data/opt/postgresql-16.0/data /docker-data/opt/postgresql/pgslave1
1.6. 重新启动从库
删除容器, 重新启动从库
# 删除容器
docker rm -f pgslave1# 重新开启容器, 注意映射目录
docker run -d -p 5501:5432 \
-e POSTGRES_PASSWORD=postgress@123 \
-v /docker-data/opt/postgresql/pgslave1/data:/var/lib/postgresql/data \
--name pgslave1 --network=pg-network -d postgres:16.4
1.7. 验证
docker logs -f pgslave1
可以看到这里已经开始同步了
或者可以使用 select * from pg_stat_wal_receiver;
create table db_order(id bigint primary key ,name varchar(255)
);insert into db_order(id,name) values (1,'zhangsan');
2. 完整命令
# 创建docker容器互联网络
docker network create pg-network# 创建映射目录
mkdir /data/postgresdocker run -d -p 5500:5432 -v /docker-data/pgmaster:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=postgress@123 \
--name pgmaster --network=pg-network postgres:16.4# 创建从库
docker run -d -p 5501:5432 \
-e POSTGRES_PASSWORD=postgress@123 \
--name pgslave1 --network=pg-network postgres:16.4# 查看容器IP pgmaster = 172.18.0.2
docker inspect pgmapgmaster = 172.18.0.2ster | grep IPAddress
# pgslave1 = 172.18.0.
docker inspect pgslave1 | grep IPAddress# 追加参数 主服务的连接信息, 用于从属服务器读取使用
# SQL用户名和密码 user=repl password=repl
cat >> /docker-data/pgmaster/postgresql.conf <<- 'EOF'
primary_conninfo = 'host=172.18.0.2 port=5432 user=repl password=repl'
EOF# 追加参数, 表示只允许这几个IP的角色repl复制数据
cat >> /docker-data/pgmaster/pg_hba.conf <<- 'EOF'
host replication repl 172.18.0.2/32 md5
host replication repl 172.18.0.3/32 md5
EOF# 设置账户
docker exec -it pgmaster /bin/bash# 登录
pgsql -U postgres
# 关闭异步提交
SET synchronous_commit = off;# 创建 角色名 = repl , 密码 = repl 的账户, 权限为登录和复制
create role repl login replication encrypted password 'repl';# 查看是否创建成功
\du# 退出
\q# ctrl + D 也可以退出
# 重启容器
docker restart pgmaster# 进入从属容器
docker exec -it pgslave1 /bin/bash
# 同步主服务器数据, 注意 这里的 /docker-data/opt/postgresql-16.0/data 是容器内部的数据
pg_basebackup -Fp --progress -D /docker-data/opt/postgresql-16.0/data/ -R -h 172.18.0.2 -p 5432 -U repl --password# 创建目录
mkdir -p /docker-data/opt/postgresql/pgslave1
# 将容器内部的数据复制到外部
docker cp pgslave1:/docker-data/opt/postgresql-16.0/data /docker-data/opt/postgresql/pgslave1# 删除容器
docker rm -f pgslave1# 重新开启容器, 注意映射目录
docker run -d -p 5501:5432 \
-e POSTGRES_PASSWORD=postgress@123 \
-v /docker-data/opt/postgresql/pgslave1/data:/var/lib/postgresql/data \
--name pgslave1 --network=pg-network -d postgres:16.4
能看到 redo starts 说明已经开始同步了
create table db_order(id bigint primary key ,name varchar(255)
);insert into db_order(id,name) values (1,'zhangsan');
查询同步状态
select * from pg_stat_wal_receiver;