PostgreSQL 10 mới được release tháng 10 năm 2017 vừa qua, nổi bật với 2 tính năng mới được kỳ vọng là Logical Replication và Declarative Partitioning (ngoài ra cũng có nhiều cải thiện và thay đổi), bài viết này mình muốn giới thiệu qua về chức năng Logical Replication và cách sử dụng trong thực tế.
Chức năng Replication của PostgreSQL bắt đầu được giới thiệu ở phiên bản PostgreSQL 9.0 dựa trên kỹ thuật chuyển WAL(Transaction log) qua standby. Chức năng này dần được cải thiện qua các phiên bản và gần đây nhất là chức năng Logical Replication trên phiên bản 10. Các phiên bản của chức năng Replication của PostgreSQL bạn có thể tham khảo ở bài viết chức năng replication của PostgreSQL.
Logical Replication được thêm vào nhờ một số nhà phát triển PostgreSQL từ công ty 2ndQuadrant dựa trên logic của module pglogical (cũng được phát triển bởi công ty này).
Trước phiên bản logical replication, PostgreSQL cũng đã thực hiện replication qua hình thức chuyển thông tin thay đổi thông qua gửi WAL tới standby. Nhưng ở những phiên bản trước, WAL chuyển qua ở mức độ chi tiết thấp, standby thực hiện phản ảnh lên DB gần như ở mức độ vật lý (đồng bộ các file dữ liệu).
Logical Replication sử dụng WAL ở mức độ chi tiết hơn, có thể decode được thành các câu lệnh SQL (phải sử dụng module ngoài để decode). Phía master (wal sender process) decode và thực hiện ghi lại WAL trước khi gửi tới standby node, phía standby sau đó sử dụng WAL nhận được và phản ảnh vào dữ liệu phía mình ở trạng thái logic thông qua logical worker process.
Logical Replication sử dụng 2 khái niệm mới, PUBLICATION và SUBSCRIPTION. PUBLICATION hiểu đơn giản là nơi phát dữ liệu cập nhật, và SUBSCRIPTION là nơi nhận cập nhật và phản ảnh vào database phía standby.
Để sử dụng chức năng này. Ta cần chỉnh wal_level (mức độ chi tiết của WAL) lên mức có thể decode được "replica", mỗi một cặp Publication & Subscription cần 1 wal sender processes và một slot chứa wal cho standby ta phải tăng parameters max_wal_senders, max_replication_slots lên giá trị cần thiết.
Parameter | Giá trị thiết lập |
---|---|
wal_level | replica |
max_wal_senders | số lượng SUBSCRIPTION + α (cho các kết nối replication khác) |
max_replication_slots | số lượng SUBSCRIPTION + α (cho các kết nối replication khác) |
Ngoài ra, để SUBSCRIPTION có thể connect tới PUBLICATION, ta phải thiết lập authentication cho kết nối replication. Chú ý, không giống với streaming replication, những thiết lập bên trên chỉ cần cho phía PUBLICATION.
Để sử dụng chức năng Logical Replication, ta cần 2 database cluster riêng biệt cho PUBLICATION và SUBSCRIPTION. Cả 2 database cluster này đều phải hỗ trợ ghi dữ liệu (không giống streaming replication, dữ liệu chỉ có thể ghi ở phía primary).
DangnoMacBook-Pro:postgres bocap$ grep -e max_replication_slots -e max_wal_senders -e wal_level $PGDATA/postgresql.conf wal_level = logical # minimal, replica, or logical #max_wal_senders = 10 # max number of walsender processes #max_replication_slots = 10 # max number of replication slots DangnoMacBook-Pro:postgres bocap$ grep replication $PGDATA/pg_hba.conf | grep -v "#" local replication all trust host replication all 127.0.0.1/32 trust host replication all ::1/128 trust DangnoMacBook-Pro:postgres bocap$
10000 postgres@postgres=# create table test_logical_rep(c1 integer primary key, c2 text); CREATE TABLE 10000 postgres@postgres=# insert into test_logical_rep select generate_series(1,5),random()::text; INSERT 0 5 10000 postgres@postgres=# table test_logical_rep postgres-# ; c1 | c2 ----+-------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.0786650250665843 (5 rows) 10000 postgres@postgres=# \h create publication Command: CREATE PUBLICATION Description: define a new publication Syntax: CREATE PUBLICATION name [ FOR TABLE [ ONLY ] table_name [ * ] [, ...] | FOR ALL TABLES ] [ WITH ( publication_parameter [= value] [, ... ] ) ] 10000 postgres@postgres=# create publication test_first_pub for table test_logical_rep ; CREATE PUBLICATION 10000 postgres@postgres=#
10001 bocap@postgres=# create table test_logical_rep(c1 integer primary key, c2 text); CREATE TABLE 10001 bocap@postgres=# \h create subscription Command: CREATE SUBSCRIPTION Description: define a new subscription Syntax: CREATE SUBSCRIPTION subscription_name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( subscription_parameter [= value] [, ... ] ) ] 10001 bocap@postgres=# create subscription test_first_sub connection 'port=10000 dbname=postgres user=bocap' publication test_first_pub; NOTICE: created replication slot "test_first_sub" on publisher CREATE SUBSCRIPTION 10001 bocap@postgres=# select * from test_logical_rep ; c1 | c2 ----+-------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.0786650250665843 (5 rows) 10001 bocap@postgres=#
Mặc định Logical Replication thực hiện đồng bộ dữ liệu ở chế độ không đồng bộ (Async). Nếu muốn thực hiện đồng bộ dữ liệu ở chế độ đồng bộ (Sync), bạn cần:
- Chỉ định tên của Subscription qua tham số application_name trong thông tin connection khi CREATE SUBSCRIPTION.
- Chỉ đinh tên của Subscription này trong tham số synchronous_standby_names (postgresql.conf) phía Publication.
-- Insert dữ liệu phía PUBLICATION 10000 postgres@postgres=# insert into test_logical_rep select 6,random()::text; INSERT 0 1 10000 postgres@postgres=# table test_logical_rep; c1 | c2 ----+-------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.0786650250665843 6 | 0.50799278402701 (6 rows) 10000 postgres@postgres=# -- Xác nhận dữ liệu cập nhật phía SUBSCRIPTION 10001 bocap@postgres=# table test_logical_rep; c1 | c2 ----+-------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.0786650250665843 6 | 0.50799278402701 (6 rows) -- Cập nhật dữ liệu phía PUBLICATION 10000 postgres@postgres=# update test_logical_rep set c2 = random()::text where c1 = 6; UPDATE 1 10000 postgres@postgres=# delete from test_logical_rep where c1 = 6; DELETE 1 10000 postgres@postgres=# table test_logical_rep; c1 | c2 ----+-------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.0786650250665843 (5 rows) -- Xác nhận thông tin cập nhật phía SUBSCRIPTION 10001 bocap@postgres=# table test_logical_rep; c1 | c2 ----+-------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.0786650250665843 (5 rows)
-- Truncate phía PUBLICATION 10000 postgres@postgres=# truncate test_logical_rep ; TRUNCATE TABLE 10000 postgres@postgres=# table test_logical_rep; c1 | c2 ----+---- (0 rows) -- Xác nhận cập nhật phía SUBSCRIPTION 10001 bocap@postgres=# table test_logical_rep; c1 | c2 ----+------------------- 1 | 0.709808008279651 2 | 0.426817617379129 3 | 0.973640063311905 4 | 0.729786423034966 5 | 0.918787303380668 (5 rows)
Facebook Comments Box