How to Setup Logical Streaming in PostgreSQL 14

2 years ago SETHA THAY 4160
How to Setup Logical Streaming in PostgreSQL 14

PostgreSQL logical replication enables sending a stream of data modifications from one server to another server. logical replication creates a line of the data modifications stream from the WAL and allows the data changes from individual tables to be replicated. The replication processes only one database at a time by sending row changes and committed transactions without allowing to send vacuum data, index changes, etc. We can selectively choose some tables within a database to put into streaming which makes logical replication more efficient on bandwidth. The downside of logical streaming is that DDL isn't handled automatically. We have to update the table definitions in sync between source and destination target ourselves, which might be complicated to get this right.

In this article, we are going to do an experiment of logical streaming replication between two databases within the same PostgreSQL 14 server. However, we still can follow the steps for the experiment in different servers scenario.

Prerequisite: You need to have the PostgreSQL database server up and running, we will provide a few articles which are related to this article
How to Install PostgreSQL 14 on Ubuntu 20.04 from Source
Installing PgBouncer as Connection Pool for PostgreSQL 14
Setting Up PostgreSQL 14 Database Cluster Using Google Cloud Engine

STEP 1: Checking WAL_LEVEL

In order to configure logical streaming in the database server, we have to change the PostgreSQL configuration file postgresql.conf with parameter wal_level to logical Using the below command to check wal_level status, if it's not set to logical we have to change and then restart the PostgreSQL service.

sethathay@instance-1:~$ sudo su - postgres
postgres@instance-1:~$ psql
psql (14.0)
Type "help" for help.
postgres=# show wal_level;
 wal_level 
-----------
 logical
(1 row)
postgres=# 

STEP 2: Create Source Database and Tables

In this step, you have to create a database schema and tables that you want to stream data to the destination. In this experiment, we are going to create the database  sourcedb schema core and two tables tb_students and tb_subjects. Follow the command below or you can create by yourself

postgres@instance-1:~$ psql
psql (14.0)
Type "help" for help.
postgres=# create database sourcedb;
CREATE DATABASE
postgres=# \c sourcedb;
You are now connected to database "sourcedb" as user "postgres".
sourcedb=# create schema core;
CREATE SCHEMA

sourcedb=# CREATE TABLE "core"."tb_students" (
sourcedb(#   "id" serial8 NOT NULL,
sourcedb(#   "card_no" varchar(255),
sourcedb(#   "full_name" varchar(500),
sourcedb(#   "gender" varchar(1),
sourcedb(#   "address" text,
sourcedb(#   CONSTRAINT "tb_students_pkey" PRIMARY KEY ("id")
sourcedb(# );
CREATE TABLE

sourcedb=# CREATE TABLE "core"."tb_subjects" (
sourcedb(#   "id" serial8 NOT NULL,
sourcedb(#   "name" varchar(500),
sourcedb(#   "credit" int8,
sourcedb(#   "outline" text,
sourcedb(#   CONSTRAINT "tb_subjects_pkey" PRIMARY KEY ("id")
sourcedb(# );
CREATE TABLE

STEP 3: Create Replication Role

We have to create a role with replication permission in order to transfer data between two regions (source and destination) of the logical replication technique. Let's name it as rep_role with password rep$$169#123

sourcedb=# CREATE ROLE rep_role WITH REPLICATION LOGIN PASSWORD 'rep$$169#123';
CREATE ROLE

Next, grant permission of replication role (rep_role) to the database sourcedb and schema core

sourcedb=# GRANT ALL PRIVILEGES ON DATABASE sourcedb TO rep_role; 
GRANT
sourcedb=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA core TO rep_role;
GRANT
sourcedb=# GRANT USAGE ON SCHEMA core TO rep_role;
GRANT

Next, allow replication role rep_role in pg_hba. This help to enable opening streaming slot of the sourcedb

#ip address of sourcedb
host    sourcedb        rep_role        xx.xx.xx.xx/32           md5
host    replication     rep_role        xx.xx.xx.xx/32           md5

Restart the service of PostgreSQL or do the reload pg_hba command below

postgres@instance-1:/data01$ vi pg_hba.conf 
postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# select pg_reload_conf(); 
 pg_reload_conf 
----------------
 t
(1 row)

Test connection from the destination server to source server using replication role that we just created (But in our case it's the same server)

postgres@instance-1:/data01$ psql -h xx.xx.xx.xx -U rep_role -d sourcedb
Password for user rep_role: 
psql (14.0)
Type "help" for help.
sourcedb=> 

STEP 4: Create Destination Database and Tables

Now let create destination database schema and tables as respectively targetdb, core, tb_students and tb_subjects

postgres@instance-1:~$ psql
psql (14.0)
Type "help" for help.
postgres=# create database targetdb;
CREATE DATABASE
postgres=# \c targetdb 
You are now connected to database "targetdb" as user "postgres".
targetdb=# create schema core;
CREATE SCHEMA

targetdb=# CREATE TABLE "core"."tb_students" (
targetdb(# "id" serial8 NOT NULL,
targetdb(# "card_no" varchar(255),
targetdb(# "full_name" varchar(500),
targetdb(# "gender" varchar(1),
targetdb(# "address" text,
targetdb(# CONSTRAINT "tb_students_pkey" PRIMARY KEY ("id")
targetdb(# );
CREATE TABLE

targetdb=# CREATE TABLE "core"."tb_subjects" (
targetdb(# "id" serial8 NOT NULL,
targetdb(# "name" varchar(500),
targetdb(# "credit" int8,
targetdb(# "outline" text,
targetdb(# CONSTRAINT "tb_subjects_pkey" PRIMARY KEY ("id")
targetdb(# );
CREATE TABLE

STEP 5: Create Publication

Now let create a new publication sourcedb and add the two tables into the publication. Let's call the publication as logical_pub

sethathay@instance-1:~$ sudo su - postgres
postgres@instance-1:~$ psql
psql (14.0)
Type "help" for help.
postgres=# \c sourcedb 
You are now connected to database "sourcedb" as user "postgres".
sourcedb=# CREATE PUBLICATION logical_pub;
CREATE PUBLICATION
sourcedb=# ALTER PUBLICATION logical_pub ADD TABLE core.tb_students;
ALTER PUBLICATION
sourcedb=# ALTER PUBLICATION logical_pub ADD TABLE core.tb_subjects;
ALTER PUBLICATION

Since we use replication on the same server, there is an additional task to configure. We have to manually create a replication slot using pg_create_logical_replication_slot that also mentioned in PostgreSQL documentation here (Section Note).

postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# \c sourcedb 
You are now connected to database "sourcedb" as user "postgres".
sourcedb=# SELECT * FROM pg_create_logical_replication_slot('logical_sub', 'pgoutput');
  slot_name  |    lsn    
-------------+-----------
 logical_sub | 0/70B17B8
(1 row)

STEP 6: Create Subscription

We will create a new subscription called logical_sub which will replicate the data from the publication we just created above step. Please note that we use the option create_slot = false since the replication is happening on the same server. If you configure in a different server there is no need to include this option.

postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# \c targetdb 
You are now connected to database "targetdb" as user "postgres".
targetdb=# CREATE SUBSCRIPTION logical_sub CONNECTION 'host=10.148.0.2 port=5432 password=rep$$169#123 user=rep_role d
bname=sourcedb' PUBLICATION logical_pub WITH (create_slot = false);
CREATE SUBSCRIPTION

STEP 7: Testing with INSERT and UPDATE Operation

Now let do the experiment by using insert and update operations on sourcedb and check the result in targetdb

- INSERT OPERATION

postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# \c sourcedb 
You are now connected to database "sourcedb" as user "postgres".
sourcedb=# insert into core.tb_students(card_no,full_name,gender,address) values('001','Setha','M','Phnom Penh');
INSERT 0 1
sourcedb=# insert into core.tb_students(card_no,full_name,gender,address) values('002','Sekada','F','Phnom Penh');
INSERT 0 1

Checking the result in taregetdb

postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# \c targetdb 
You are now connected to database "targetdb" as user "postgres".
targetdb=# select * from core.tb_students;
 id | card_no | full_name | gender |  address   
----+---------+-----------+--------+------------
  1 | 001     | Setha     | M      | Phnom Penh
  2 | 002     | Sekada    | F      | Phnom Penh
(2 rows)
targetdb=# 

- UPDATE OPERATION

postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# \c sourcedb 
You are now connected to database "sourcedb" as user "postgres".
sourcedb=# update core.tb_students SET full_name='Setha Thay' WHERE card_no='001';
UPDATE 1
sourcedb=#

Checking the result in taregetdb

postgres@instance-1:/data01$ psql
psql (14.0)
Type "help" for help.
postgres=# \c targetdb 
You are now connected to database "targetdb" as user "postgres".
targetdb=# select * from core.tb_students where card_no='001';
 id | card_no | full_name  | gender |  address   
----+---------+------------+--------+------------
  1 | 001     | Setha Thay | M      | Phnom Penh
(1 row)
targetdb=#

THANK YOU, Find Us @
Facebook
Telegram
Twitter
LinkedIn


About author

Author Profile

SETHA THAY

Software Engineer & Project Manager. I am willing to share IT knowledge, technical experiences and investment to financial freedom. Feel free to ask and contact me.



Scroll to Top