์ด ๋ฌธ์์์๋ ๊ฒ์์ ํด๋ฌ์คํฐ์ ๊ตฌ๋ ์ ํด๋ฌ์คํฐ๋ฅผ ๋ง๋ค๊ณ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ์๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์ AlloyDB Omni ๊ฐ์๋ฅผ ์์งํด์ผ ํฉ๋๋ค. PostgreSQL ๋ ผ๋ฆฌ ๋ณต์ ์ ์ ํ์ฌํญ๋ ์์์ผ ํฉ๋๋ค.
์ด ํ์ด์ง์ ์ฝ๋ ์ค๋ํซ์ ๊ฐ์ ์์ฒด AlloyDB Omni ๋ฆฌ์์ค์ ๊ฐ์ผ๋ก ๋์ฒดํ์ฌ ๋ชจ๋ธ๋ก ์ฌ์ฉํ ์ ์๋ ์์์ ๋๋ค.
ํด๋ฌ์คํฐ ๋ง๋ค๊ธฐ
Kubernetes์ Omni Operator๋ฅผ ์ค์นํฉ๋๋ค.
๊ฒ์์ ํด๋ฌ์คํฐ๋ฅผ ๋ง๋ญ๋๋ค.
$ cat << EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: db-pw-publisher type: Opaque data: publisher: "b2RzcGFzc3dvcmQ=" # Password is odspassword --- apiVersion: alloydbomni.dbadmin.goog/v1 kind: DBCluster metadata: name: publisher spec: primarySpec: adminUser: passwordRef: name: db-pw-publisher databaseVersion: "15.5.4" resources: memory: 10Gi cpu: 1 disks: - name: DataDisk size: 40Gi EOF
๊ตฌ๋ ์ ํด๋ฌ์คํฐ๋ฅผ ๋ง๋ญ๋๋ค.
$ cat << EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: db-pw-subscriber type: Opaque data: subscriber: "b2RzcGFzc3dvcmQ=" # Password is odspassword --- apiVersion: alloydbomni.dbadmin.goog/v1 kind: DBCluster metadata: name: subscriber spec: primarySpec: adminUser: passwordRef: name: db-pw-subscriber databaseVersion: "15.5.4" resources: memory: 10Gi cpu: 1 disks: - name: DataDisk size: 40Gi EOF
๊ฒ์์ ํด๋ฌ์คํฐ ๊ตฌ์ฑ
๊ฒ์์ ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํ๊ณ ํ ์ด๋ธ์ ๋ง๋ญ๋๋ค. ์ ํ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ํ ์คํธ๋ก ๊ฒ์ํ์ฌ ๊ตฌ๋ ์์๊ฒ ๋ณต์ ๋๋์ง ํ์ธํ ์ ์์ต๋๋ค.
wal_level
๋งค๊ฐ๋ณ์๋ฅผlogical
๋ก ์ ๋ฐ์ดํธํฉ๋๋ค.$ kubectl patch dbclusters.al publisher -p '{"spec":{"primarySpec":{"parameters":{"wal_level":"logical"}}}}' --type=merge
ํ์ํ ํฌ๋๋ฅผ ์ฐพ์ต๋๋ค.
$ kubectl get pod -l "alloydbomni.internal.dbadmin.goog/dbcluster=publisher, alloydbomni.internal.dbadmin.goog/task-type=database, dbs.internal.dbadmin.goog/ha-role=Primary"
๊ฒ์์ ํด๋ฌ์คํฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํฌ๋์ ๋ก๊ทธ์ธํฉ๋๋ค.
NAME READY STATUS RESTARTS AGE al-2bce-publisher-0 3/3 Running 0 36m $ kubectl exec -ti al-2bce-publisher-0 -- /bin/bash
customer
๋ผ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ง๋ญ๋๋ค.CREATE DATABASE customer;
์ ํ์ฌํญ: ํ ์คํธ ๋ชฉ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ ์ถ๊ฐํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํฉ๋๋ค. ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์์์์ ๊ตฌ๋ ์๋ก์ ๋ฐ์ดํฐ ๋ณต์ ๋ฅผ ๊ด์ฐฐํ ์ ์์ต๋๋ค.
$ psql -h localhost -U postgres customer customer=# CREATE TABLE COMPANY( customer(# ID INT PRIMARY KEY NOT NULL, customer(# NAME TEXT NOT NULL, customer(# AGE INT NOT NULL, customer(# SALARY REAL customer(# ); CREATE TABLE customer=# INSERT INTO COMPANY (ID,NAME,AGE,SALARY) VALUES customer-# (1, 'Quinn', 25, 65000.00), customer-# (2, 'Kim', 22, 72250.00), customer-# (3, 'Bola', 31, 53000.00), customer-# (4, 'Sasha', 33, 105000.00), customer-# (5, 'Yuri', 27, 85000.00); INSERT 0 5 customer=# \dt List of relations Schema | Name | Type | Owner --------+---------+-------+---------- public | company | table | postgres (1 row) customer=# select * from company; id | name | age | salary ----+-------+-----+-------- 1 | Quinn | 25 | 65000 2 | Kim | 22 | 72250 3 | Bola | 31 | 53000 4 | Sasha | 33 | 105000 5 | Yuri | 27 | 85000 (5 rows)
๋ณต์ ๋ฐ ๊ถํ ๋ถ์ฌ๋ฅผ ์ํ ์ฌ์ฉ์
logicalreplica
๋ฅผ ๋ง๋ญ๋๋ค.CREATE USER logicalreplica WITH REPLICATION LOGIN PASSWORD '123';
๊ถํ ๋ถ์ฌ ์ด ์์์์๋ ๊ณต๊ฐ ์คํค๋ง๋ฅผ ์ฌ์ฉํฉ๋๋ค.
GRANT SELECT ON ALL TABLES IN SCHEMA public TO logicalreplica; GRANT USAGE ON SCHEMA public TO logicalreplica; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO logicalreplica;
customer
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฒ์๋ฅผ ๋ง๋ญ๋๋ค.CREATE PUBLICATION pub_customer; ALTER PUBLICATION pub_customer ADD TABLE company;
๊ตฌ๋ ์ ํด๋ฌ์คํฐ ๊ตฌ์ฑ
๊ฒ์์ ํด๋ฌ์คํฐ์์ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ๋ฅผ ์์ ํ๋๋ก ๊ตฌ๋ ์ ํด๋ฌ์คํฐ๋ฅผ ์ฌ์ฉ ์ค์ ํฉ๋๋ค.
๊ตฌ๋ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์
wal_level
๋งค๊ฐ๋ณ์๋ฅผlogical
๋ก ์ค์ ํฉ๋๋ค.$ kubectl patch dbclusters.al subscriber -p '{"spec":{"primarySpec":{"parameters":{"wal_level":"logical"}}}}' --type=merge
ํ์ํ ํฌ๋๋ฅผ ์ฐพ์ต๋๋ค.
$ kubectl get pod -l "alloydbomni.internal.dbadmin.goog/dbcluster=subscriber, alloydbomni.internal.dbadmin.goog/task-type=database, dbs.internal.dbadmin.goog/ha-role=Primary"
๊ตฌ๋ ์ ํด๋ฌ์คํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํฌ๋์ ๋ก๊ทธ์ธํฉ๋๋ค.
$ kubectl get pod NAME READY STATUS RESTARTS AGE al-2bce-publisher-0 3/3 Running 0 20h $ kubectl exec -ti al-3513-subscriber-0 -- /bin/bash Defaulted container "database" out of: database, logrotate-agent, memoryagent, dbinit (init) postgres@al-3513-subscriber-0:/$
10.116.14.190
๊ณผ ๊ฐ์ ๊ฒ์์ ํฌ๋์ IP ์ฃผ์๋ฅผ ์ฐพ์ต๋๋ค.$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE al-publisher-rw-ilb ClusterIP 10.116.14.190 <none> 5432/TCP 21h
๊ฒ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฒ์๋ ๋ฐ์ดํฐ ์ด๊ธฐ ์ฌ๋ณธ์ผ๋ก ๊ฒ์์์์ ์คํค๋ง ๋ฐฑ์ ์ ์ํํฉ๋๋ค. ๋ ผ๋ฆฌ์ ๋ณต์ ๋ DDL ๋ณต์ ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค. ๋ ผ๋ฆฌ์ ๋ณต์ ๊ฐ ์์๋๊ธฐ ์ ์ ๋ณต์ ํ๋ ค๋ ์คํค๋ง ๋๋ ํ ์ด๋ธ์ด ๋์(๊ตฌ๋ ์ ํด๋ฌ์คํฐ)์ ์์ด์ผ ํฉ๋๋ค.
postgres@al-3513-subscriber-0:/$ pg_dump -h 10.116.14.190 -U postgres --create --schema-only customer > /tmp/customer.schema-only.sql
๊ตฌ๋ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐฑ์ ์ ์ ์ฉํฉ๋๋ค.
postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres < /tmp/customer.schema-only.sql
์ ํ์ฌํญ: ํ ์ด๋ธ์ ๋ฐ์ดํฐ๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.
# There is no data in table company customer=# select * from company; id | name | age | salary ----+------+-----+-------- (0 rows)
๋ฐ์ดํฐ๋ฒ ์ด์ค
customer
์ ๊ตฌ๋ ์ ๋ง๋ญ๋๋ค.postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer customer=# CREATE SUBSCRIPTION sub_customer CONNECTION 'host=10.116.14.190 port=5432 user=logicalreplica dbname=customer password=123' PUBLICATION pub_customer;
์ ํ์ฌํญ: ๊ฒ์์ ํด๋ฌ์คํฐ์์ ๋ณต์ ๋ฅผ ํ์ธํฉ๋๋ค.
postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer customer=# select * from public.company; id | name | age | salary ----+-------+-----+-------- 1 | Quinn | 25 | 65000 2 | Kim | 22 | 72250 3 | Bola | 31 | 53000 4 | Sasha | 33 | 105000 5 | Yuri | 27 | 85000 (5 rows)
๊ฒ์์ ํด๋ฌ์คํฐ์์ ํ ์ด๋ธ์ ํ์ ์ถ๊ฐํฉ๋๋ค.
# On the publisher database $ kubectl exec -ti al-2bce-publisher-0 -- /bin/bash Defaulted container "database" out of: database, logrotate-agent, memoryagent, dbinit (init) postgres@al-2bce-publisher-0:/$ psql -h localhost -U postgres customer customer=# insert into company(id, name, age, salary) values (6, 'Alex', 39, 100000);
๊ตฌ๋ ์ ํด๋ฌ์คํฐ์์ ๊ฒ์์ ํด๋ฌ์คํฐ์ ํ ์ด๋ธ์ ์ถ๊ฐ๋ ํ์ด ๊ตฌ๋ ์ ํด๋ฌ์คํฐ์ ํ ์ด๋ธ์ ๋ณต์ ๋์๋์ง ํ์ธํฉ๋๋ค.
# On the subscriber database, data is synced. postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer customer=# select * from company; id | name | age | salary ----+-------+-----+-------- 1 | Quinn | 25 | 65000 2 | Kim | 22 | 72250 3 | Bola | 31 | 53000 4 | Sasha | 33 | 105000 5 | Yuri | 27 | 85000 6 | Alex | 39 | 100000 (6 rows)
์ถ๊ฐ ํ ์ด๋ธ ์๋์ผ๋ก ๋ง๋ค๊ธฐ
๋
ผ๋ฆฌ์ ๋ณต์ ๋ pglogical
์ replicate_ddl_command
์ ๋ฌ๋ฆฌ DDL ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ๋๊ธฐํํ์ง ์์ต๋๋ค. ์คํ์์ค ๋๊ตฌ pgl_ddl_deploy
์์ ์๋ฃจ์
์ ์ ๊ณตํ์ง๋ง ๊ตฌ๋
์์์ DDL ๋ช
๋ น์ด๋ฅผ ์๋์ผ๋ก ์คํํ ์๋ ์์ต๋๋ค.
์ด๋ฅผ ์ดํด๋ณด๊ธฐ ์ํด ๊ฒ์์ ํด๋ฌ์คํฐ์
customer
๋ฐ์ดํฐ๋ฒ ์ด์ค์finance
๋ผ๋ ์ ํ ์ด๋ธ์ ๋ง๋ญ๋๋ค.# On the publisher database $ kubectl exec -ti al-2bce-publisher-0 -- /bin/bash Defaulted container "database" out of: database, logrotate-agent, memoryagent, dbinit (init) postgres@al-2bce-publisher-0:/$ psql -h localhost -U postgres customer customer=# create table finance (row text); CREATE TABLE customer=# insert into finance values ('critical data'); INSERT 0 1 customer=# ALTER PUBLICATION pub_customer ADD TABLE finance; ALTER PUBLICATION
๊ฒ์์ ํด๋ฌ์คํฐ์ ์ ํ ์ด๋ธ์ด ์ถ๊ฐ๋๋ฉด ๊ตฌ๋ ์์์ DDL(ํ ์ด๋ธ ์์ฑ)์ ์๋์ผ๋ก ์ ์ฉํ ๋ค์ ๊ตฌ๋ ์ ํด๋ฌ์คํฐ์์ ๋ค์์ ์คํํ์ฌ ๋ณต์ ๋ฅผ ํ์ธํฉ๋๋ค.
postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer customer=# create table finance (row text); CREATE TABLE customer=# ALTER SUBSCRIPTION sub_customer REFRESH PUBLICATION; ALTER SUBSCRIPTION customer=# select * from finance; row --------------- critical data (1 row)