이 문서는 PostgreSQL에서 데이터베이스 복제의 기본을 연습하고 싶지만 원격 서버에 액세스할 수 없는 초보자를 대상으로 합니다. 새로운 기술을 배울 때는 자신의 컴퓨터에서 예제를 실행하여 개념을 확고히 하는 것이 중요하다고 생각합니다. 복제본의 경우, 사용 가능한 많은 리소스가 사용자가 PostgreSQL에 대해 어느 정도 경험이 있고 복제본을 실행하는 다른 서버에 액세스할 수 있다고 가정하기 때문에 이 작업이 어려울 수 있습니다. 여기서는 어떠한 가정도 하지 않으며, 유일한 전제 조건은 Postgres가 설치되어 있고 셸에 로그인할 수 있다는 것입니다.
준비
이 예제에서는 우분투 22.10을 사용하여 PostgreSQL 16을 실행했습니다.
$HOME/pg/data
데이터 디렉터리로 $HOME/pg/data를 사용합니다. 첫 번째 예에서는 스트리밍 물리적 복제의 사용을 소개하고, 로그 전송을 사용하는 물리적 복제의 짧은 예, 논리적 복 제의 예, 마지막으로 다양한 복제 유형과 그 기능에 대한 요약을 소개합니다.
스트리밍 물리적 복제
먼저 메인 서버에 수퍼유저(일반적으로 기본 사용자 "postgres"로 로그인합니다.
psql -U postgres
셸에 들어간 후 복제를 위한 새 역할을 만들고, 마스터 서버에 테이블을 만들고, 해당 테이블에 데이터를 삽입한 다음 종료합니다.
postgres=# CREATE ROLE rep_user WITH REPLICATION LOGIN PASSWORD 'rep_pass';
postgres=# create table t1(a int, b int);
postgres=# insert into t1 values (1,2);
postgres=# \q
를 열고 다음을 확인합니다.
listen_addresses = 'localhost'
그런 다음 $HOME/pg/data/pg_hba.conf 끝에 다음을 추가합니다.
host replication rep_user localhost md5
다음 명령을 실행하여 기본 서버의 백업을 만든 다음 이를 복제 서버의 데이터 디렉터리로 사용합니다.
$ pg_basebackup -h localhost -U rep_user -X stream -C -S replica_1 -v -R -W -D $HOME/pg/rep
이 디렉터리를 만든 후 $HOME/pg/rep/postgres.conf 열고 포트 번호를 PostgreSQL 기본값인 5432가 아닌 다른 값으로 설정합니다.
port = 5433
그런 다음 postgres.conf에서 primary_conninfo로 시작하는 줄을 편집하여 다음과 같이 표시되도록 합니다.
primary_conninfo = 'dbname=postgres user=postgres host=localgost port=5432 sslmode=disable'
서버를 시작하기 위해 마지막으로 해야 할 일은 복제본 서버의 데이터 폴더에 빈 standby.signal 파일을 만드는 것입니다. 명령줄에 다음을 입력합니다:
$ touch $HOME/pg/rep/standby.signal
두 번째 터미널을 열면 호스트에서 각각 다른 포트에서 두 개의 개별 PostgreSQL 인스턴스가 시작되므로 두 번째 터미널을 엽니다.
첫 번째 터미널에 입력합니다:
pg_ctl -D $HOME/pg/data start
두 번째 터미널에 입력합니다:
pg_ctl -D $HOME/pg/rep start
각각 서버가 가동 중임을 나타내는 출력을 제공해야 합니다. 다음을 입력하면 이를 확인할 수 있습니다:
$ ps -aux | grep postgres
tristen 29088 0.0 0.1 175596 18580 ? Ss 15:42 0:00 /home/tristen/disk/pgapp/bin/postgres -D /home/tristen/pg/data
tristen 29089 0.0 0.0 175728 2388 ? Ss 15:42 0:00 postgres: checkpointer
tristen 29090 0.0 0.0 175752 2364 ? Ss 15:42 0:00 postgres: background writer
tristen 29092 0.0 0.0 175596 7424 ? Ss 15:42 0:00 postgres: walwriter
tristen 29093 0.0 0.0 177196 4892 ? Ss 15:42 0:00 postgres: autovacuum launcher
tristen 29094 0.0 0.0 177176 4984 ? Ss 15:42 0:00 postgres: logical replication launcher
tristen 29112 0.0 0.1 175596 18456 ? Ss 15:42 0:00 /home/tristen/disk/pgapp/bin/postgres -D /home/tristen/pg/rep
tristen 29113 0.0 0.0 175728 2564 ? Ss 15:42 0:00 postgres: checkpointer
tristen 29114 0.0 0.0 175596 2564 ? Ss 15:42 0:00 postgres: background writer
tristen 29115 0.0 0.0 176348 4488 ? Ss 15:42 0:00 postgres: startup recovering 000000010000000000000014
tristen 29116 0.0 0.0 176136 3664 ? Ss 15:42 0:00 postgres: walreceiver streaming 0/14000110
tristen 29117 0.0 0.0 177336 7060 ? Ss 15:42 0:00 postgres: walsender rep_user .1(39650) streaming 0/14000110
tristen 29126 0.0 0.0 17580 2252 pts/2 S+ 15:42 0:00 grep --color=auto postgres
두 $HOME/disk/pgapp/bin/postgres 다른 디렉터리에서 실행 중인 두 개의 프로세스가 있음을 알 수 있습니다.
이제 두 인스턴스 각각에 연결이 이루어집니다. 첫 번째는 첫 번째 터미널의 마스터 서버입니다:
psql -U postgres -p 5432
그런 다음 두 번째 터미널의 복제 서버입니다:
psql -U postgres -p 5433
-p 플래그는 포트를 지정하는 데 사용됩니다. 마스터 서버에서 이 플래그를 사용하면 기본 포트를 사용하므로 중복됩니다. 그러나 두 개의 서로 다른 포트에 연결하므로 두 개의 서로 다른 PostgreSQL 인스턴스에 연결된다는 것을 나타내는 좋은 표시입니다.
Postgres 셸에 \d를 입력하면 데이터베이스의 테이블 목록을 가져올 수 있습니다. 복제 서버에 해당하는 두 번째 터미널에서 테이블 t1이 실제로 복제된 것을 볼 수 있습니다.
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | t1 | table | postgres
(1 row)
이제 기본 서버에 새 테이블을 만들어 복제 서버에 자동으로 복제될 것임을 표시합니다.
첫 번째 터미널을 입력합니다:
postgres=# create table t2(c int, d text);
CREATE TABLE
postgres=# insert into t2 values (3, 'hello');
INSERT 0 1
두 번째 터미널에 입력합니다:
postgres=# select * from t2;
c | d
---+-------
3 | hello
(1 row)
보시다시피 새 테이블이 마스터 서버에서 복사될 뿐만 아니라 방금 삽입된 데이터도 복사됩니다.
이 복제 관계는 단방향이라는 점에 주목할 필요가 있습니다. 즉, 복제 서버는 마스터 서버에서만 복제할 수 있습니다. 복제 서버에서 테이블을 만들려고 하면 오류 메시지가 표시됩니다:
ERROR: cannot execute CREATE TABLE in a read-only transaction
논리적으로는 마스터 서버의 데이터를 더 쉽게 사용할 수 있도록 복제본을 읽기 전용으로 설정하는 것이 바람직하기 때문입니다.
로그 전송 물리적 복제
로그 전송 물리적 복제는 스트리밍 물리적 복제와 설정이 비슷하며, 주로 몇 가지 구성 파일만 변경합니다. 마스터 서버에서 postgresql.conf 편집
wal_level = replica
archive_mode = on
archive_command = 'cp %p /path/to/archive/%f'
서버가 실행 중인 경우 서버를 다시 시작하고 기본 서버의 백업을 만듭니다:
$ pg_basebackup -h localhost -U rep_user -X fetch -v -R -W -D $HOME/pg/rep
를 열고 두 줄을 편집합니다. 보관_명령으로 시작하는 줄에 주석을 달고 복원_명령으로 시작하는 줄의 주석을 없애고 = 뒤에 복원할 때 사용할 명령을 추가합니다. 이 줄은 다음과 같이 표시되어야 합니다:
#archive_command = 'cp %p /path/to/archive/%f'
restore_command = 'cp /path/to/archive/%f %p'
스트리밍 물리적 복제 예제에서와 같이 두 서버를 모두 시작하면 복제본이 마스터 서버를 복제하는 것을 볼 수 있습니다. 로그 전송 변경 사항은 스트리밍 물리적 복제만큼 실시간이 아닐 수 있습니다. 로그 전송 복제는 지연 시간이 더 길고 WAL 파일이 복제본에 채워질 때만 변경 내용을 전송합니다.
논리적 복제
논리적 복제는 서버의 물리적 복제와 초기 설정이 동일합니다. 여기에는 몇 가지 다른 구성과 테이블을 작동시키기 위한 몇 가지 수동 편집이 포함됩니다.
마스터 서버에서 postgresql.conf 편집하기
wal_level = logical
마스터 서버의 pga_hba.conf에 복제된 사용자에 대한 올바른 연결 권한이 포함되어 있는지 확인합니다.
host all rep_user localhost md5
모든 구성이 완료되면 두 서버를 모두 시작하고 셸에 로그인합니다. 예제에서는 각 서버가 서로 다른 포트 번호를 사용하므로 같은 서버를 두 번 사용하지 않도록 주의하세요! 각 서버의 셸에서 각 서버에 동일한 이름과 구조의 테이블을 만들어야 합니다. 테이블이 완전히 다른 경우 복제본이 테이블을 찾을 수 없고 오류가 발생합니다. 즉, 두 터미널에 다음을 입력합니다:
postgres=# create table t1(id int, val text);
이제 두 데이터베이스에 동일한 빈 테이블이 생겼으므로 다음 명령을 계속 진행하여 테이블을 복사합니다. 마스터 서버에 다음 명령을 입력하여 테이블 t1에 대한 게시를 만듭니다:
postgres=# CREATE PUBLICATION pub_t1 FOR TABLE t1;
이렇게 하면 테이블 t1에 대한 게시가 생성되며, 이는 테이블 t1이 복제 서버에 복제된다는 의미입니다. 게시의 일부로 몇 개의 테이블을 복제할 수 있습니다.
게시를 생성한 후 복제 데이터베이스의 테이블 t1을 마스터 데이터베이스의 테이블 t1에 구독합니다. 이렇게 하려면 아래와 같이 복제 데이터베이스에 구독을 만들어야 합니다:
postgres=# CREATE SUBSCRIPTION sub_t1 CONNECTION 'dbname=postgres host=localhost port=5432 user=postgres' PUBLICATION pub_t1;
이 예에서는 기본 사용자인 postgres와 기본 데이터베이스인 postgres가 모두 사용되었지만 반드시 사용해야 하는 것은 아닙니다.
이제 구독이 생성되었으므로 기본 서버의 테이블 t1에 있는 모든 업데이트가 복제본 서버의 테이블 t1에 표시됩니다. 게시를 수행하지 않은 마스터 서버의 다른 테이블은 복제본에 복제되지 않습니다. 이제 기본 데이터베이스 터미널의 테이블 t1에 일부 데이터를 삽입하여 테스트를 수행합니다:
postgres=# insert into t1 values (1, 'hello');
INSERT 0 1
postgres=# insert into t1 values (2, 'world');
INSERT 0 1
이제 테이블이 실제로 복제 서버에 복제되는지 확인해 보겠습니다:
postgres=# select * from t1;
id | val
----+-------
1 | hello
2 | world
(2 rows)
이제 데이터가 복제 서버에 성공적으로 복제되었습니다. 하지만 이것이 실제 복제인지 아닌지 어떻게 알 수 있을까요? 마스터 데이터베이스에 새 테이블을 추가하고 데이터를 삽입해 보겠습니다:
postgres=# create table t2(c int, d int);
CREATE TABLE
postgres=# insert into t2 values(3,4);
INSERT 0 1
postgres=# insert into t2 values(5,6);
INSERT 0 1
사본을 다시 확인하세요:
postgres=# select * from t2;
ERROR: relation "t2" does not exist
LINE 1: select * from t2;
t2 테이블이 구독되지 않아 복제본에 존재하지 않으므로 복제되지 않는 것을 볼 수 있습니다. 이렇게 하면 일부 테이블을 중앙 데이터베이스에서 원격 데이터베이스로 공개하고 다른 테이블은 비공개로 유지할 수 있습니다.
하지만 복제본 데이터베이스의 테이블 구조가 변경되면 어떻게 될까요? 테스트해 봅시다. 기본 데이터베이스 터미널에서 테이블 구조를 변경하고 데이터를 추가합니다:
postgres=# alter table t1 add column x int;
ALTER TABLE
postgres=# insert into t1 values (3, 'foo', 42);
INSERT 0 1
postgres=# insert into t1 values (4, 'bar', 10);
INSERT 0 1
postgres=# select * from t1;
id | val | x
----+-------+----
1 | hello |
2 | world |
3 | foo | 42
4 | bar | 10
(4 rows)
이제 복제본 서버를 확인합니다:
postgres=# select * from t1;
id | val
----+-------
1 | hello
2 | world
(2 rows)
복제 서버가 더 이상 기본 서버를 복제하지 않는다는 것을 알 수 있습니다. 동일한 스키마의 새 데이터가 기본 데이터베이스에 추가되더라도 복제본에는 표시되지 않습니다:
postgres=# insert into t1 values (15, 'test');
INSERT 0 1
postgres=# select * from t1;
id | val
----+-------
1 | hello
2 | world
(2 rows)
t1의 스키마를 변경한 결과, 복제본은 이제 실제로는 다른 테이블이므로 더 이상 데이터를 복사하지 않습니다. 테이블의 스키마를 변경하고 복제본을 다른 곳에서 실행하는 경우 이 점을 기억하는 것이 중요합니다.
복제본에 마스터 서버의 테이블과 일치하는 테이블을 만들지 않으면 어떻게 되나요?
postgres=# CREATE PUBLICATION pub_t2 FOR TABLE t2;
CREATE PUBLICATION
postgres=# CREATE SUBSCRIPTION sub_t2 CONNECTION 'dbname=postgres host=localhost port=5432 user=postgres' PUBLICATION pub_t2;
ERROR: relation "public.t2" does not exist
그러면 구독하려는 관계가 존재하지 않는다는 오류 메시지가 표시됩니다. 모든 연결 정보가 제공되었고 해당 위치에 테이블 t2가 존재한다는 것을 알고 있기 때문에 매우 혼란스러울 수 있습니다. 그러나 이 오류는 현재 있는 복제본에서 테이블 t2를 찾을 수 없으므로 구독을 만들 수 없음을 의미합니다. 따라서 논리적 복제가 제대로 작동하려면 두 데이터베이스 모두 동일한 스키마를 가진 동일한 테이블을 포함해야 한다는 점을 기억해야 합니다.
비교
아래는 개괄적인 관점에서 논의된 모든 주제를 요약한 것입니다. 어떤 복제 방법을 사용할지 아직 결정하지 못했다면 이 요약이 결정을 내리는 데 도움이 될 수 있습니다.
논리적 복제와 물리적 복제
| 행 수준에서 작업하면 개별 데이터베이스 행에 대한 변경 사항이 기본 서버에서 복제 서버로 복제됩니다. 논리적 복제는 복제할 테이블, 스키마, 열까지 선택할 수 있어 더욱 세분화된 기능을 제공합니다. | 디스크 블록 수준에서 작동하여 기본 서버에서 복제본으로 데이터를 복사합니다. 따라서 시간과 공간 모두에서 더 효율적입니다. |
| 로직이 행 수준에서 작동하기 때문에 서로 다른 PostgreSQL 버전 간 또는 서로 다른 운영 체제에서 실행되는 PostgreSQL 인스턴스 간에도 백업할 수 있습니다. | 전체 데이터베이스 클러스터가 복제되므로 논리적 복제의 세분성을 사용할 수 없습니다. |
| 논리적 복제는 양방향 또는 다중 마스터 복제 설정을 지원합니다. | 또한 복사본을 만들려면 동일한 운영 체제에서 동일한 PostgreSQL 버전을 실행해야 합니다. |
| 논리적 복제는 물리적 복제보다 효율성이 떨어집니다. | 물리적 복제에는 전송과 스트리밍의 두 가지 유형이 있습니다. |
논리적 복제와 물리적 복제
로깅 및 스트리밍 복제
| 변경이 이루어지면 마스터 서버에서 복제본으로 전송됩니다. 이렇게 하면 지연 시간이 줄어들고 복제본이 마스터 서버와 동기화 상태를 유지할 수 있습니다. | 거의 실시간에 가깝게 변경 사항이 발생하는 즉시 전송하지 않고 WAL 파일이 가득 차거나 구성 가능한 시간 초과에 도달한 후에 전송합니다. 상대적으로 지연 시간이 길다. |
| WAL 레코드를 복제본에 지속적으로 전송하고, 복제본은 이를 재생하여 동기화 상태를 유지합니다. | 파일 수준에서 작업하는 WAL 파일은 기본 서버에 보관되고 복제 서버로 복사됩니다. 이 작업은 수동 전송 또는 스크립트를 통해 수행되며, WAL 파일은 마스터 서버와 동기화 상태를 유지하기 위해 재생됩니다. |
| 더 효율적이고, 리소스 사용량이 적으며, WAL 파일을 복사하거나 보관할 필요가 없습니다. | 덜 효율적이고 리소스 집약적인 |
| 영구 연결 필요 | 영구적인 연결이 필요하지 않으며 연결이 불안정하거나 지연 시간이 긴 환경에 적합합니다. |
| 사본은 읽기 전용입니다. 쿼리 로드 밸런싱, 고가용성 및 백업에는 유용하지만 쓰기에는 유용하지 않습니다. | 사본은 읽기 전용 또는 읽기-쓰기로 구성할 수 있습니다. |
물리적 복제 스트리밍과 로그 전송 물리적 복제 비교
비동기식 대 동기식 스트리밍 복제
| 기본 서버가 사용 중이면 복제본이 기본 서버보다 뒤처질 수 있습니다. 기본 서버가 충돌하면 복제되지 않은 데이터가 손실됩니다. 더 높은 성능 | 마스터 서버는 복제본이 트랜잭션을 수신했다는 확인을 받을 때까지 커밋하지 않습니다. 기본 데이터베이스가 충돌해도 데이터는 손실되지 않지만, 이 방법은 기본 데이터베이스의 속도를 늦추거나 복제본에 문제가 있는 경우 중단될 수도 있습니다. 네트워크 지연으로 인한 성능 영향도 있습니다. |
비동기 스트리밍과 동기 스트리밍 비교
요약
이것으로 다양한 복제 방법에 대한 PostgreSQL로 서버 복제를 설정하는 방법에 대한 글을 마칩니다. 먼저 각 방법을 설정하고 실행하는 실제 단계를 검토한 다음 각 방법의 기능에 대한 개괄적인 요약을 살펴보았습니다.
. PostgreSQL 설명서. 에서 검색된 날짜: 2023년 3월 29일 www.postgresql.org/docs/curren...
. PostgreSQL 설명서. 에서 검색된 날짜: 2023년 3월 29일
B, A. . [웹 로그]. 검색된 날짜: 2023년 3월 29일,
레비나스, M. . [웹 로그]. 검색된 날짜: 2023년 3월 29일
Ravoof, S.. [웹 로그]. 검색 됨 3 월 29, 2023에서 가져온 것 kinsta.com/blog/postgr....
원본 주소 로컬에서 PostgreSQL 복제 서버 설정하기 - Highgo Software Inc.





