2.18로 업그레이드하기#
AgensGraph 2.18은 PostgreSQL 18 위에 만들어졌으므로 그리로 옮기는 것은 메이저 버전
업그레이드입니다. 데이터 디렉터리 형식이 바뀌었고, 2.17 데이터 디렉터리는 2.18 바이너리로 기동할 수
없습니다. 경로는 둘입니다. 기존 데이터 파일을 재사용해 빠른 pg_upgrade, 또는 덤프 후 다시
적재하는 것입니다.
어느 쪽이든 하기 전에 무엇이 바뀌었는지를 읽고 자기 애플리케이션을 그에 비추어 확인하십시오. 2.17에서 잘 도는 쿼리를 망가뜨릴 변경이 여럿 있고, 업그레이드 도구는 그중 어느 것도 잡아 주지 않습니다.
애플리케이션부터 확인하기#
이 목록을 자기 코드베이스에 대고 하나씩 짚어 보십시오. 각 항목은 2.17에서 잘 돌던 코드를 2.18에서 오류나 다른 답으로 바꾸는 변경입니다.
xor·current_graph·current_property_graph라는 이름의 식별자 — 이제 예약어입니다. 이름을 바꾸거나 큰따옴표로 감싸십시오(MATCH (n:"xor")). 여기서 백틱은 따옴표가 아닙니다. 변수 이름으로 쓰는let과finish, 레이블로 쓰는let도 거부되며, 패턴 표기MATCH (n:insert)는 여전히 되지만CREATE VLABEL insert;에는 따옴표가 필요합니다. 어느 단어가 어느 자리에서 실패하는지의 표는 키워드를 참고하십시오.call(...)또는(call { ... })— 이름이 글자 그대로call인 함수, 또는 변수가call이고 레이블 없이 속성 맵을 지닌 정점 패턴입니다. 둘 다 뜻이 달라지므로 이름을 따옴표로 감싸십시오.불리언이 아닌 조건 —
WHERE n.count,FILTER n.name입니다. 전에는 0이 아닌지, 비어 있지 않은지로 골랐지만 이제 형 변환 오류를 냅니다.::boolean을 붙이거나 명시적으로 비교하십시오.정점·간선·경로에 대한
collect()— 이제 사본을 담은 jsonb 배열이 아니라 네이티브 배열을 반환합니다. jsonb 형태를 파싱하던 클라이언트 코드는 고쳐야 하고, 모은 요소에서 속성을 읽던 코드는 이제 동작하기 시작합니다.정점이나 간선에 대한
min()/max()— 이제 모호해져 오류입니다.min(v::jsonb)이나min(id(v))를 쓰십시오.range()·toStringList·toIntegerList·toFloatList— 반환 타입이 바뀌었습니다.SKIP이나LIMIT이 붙은WITH … WHERE— 이제 걸러 낸 뒤에 나누므로 결과 집합이 달라집니다.그래프에 대한 행 수준 보안 — 이제 RLS가 그래프 쓰기에 실제로 적용됩니다. 레이블에 정책이 걸려 있다면 다시 시험하십시오. 전에는 빠져나가던 쓰기가 거부됩니다.
레이블에 대한
ALTER TABLE— 구조를 바꾸는 것은 모두 거부됩니다. 레이블 DDL을 쓰거나enable_graph_ddl을 설정하십시오.EXPLAIN회귀 기준 — 요소에 대한count(), 속성 읽기, 가변 길이 순회 노드에서 계획 텍스트가 바뀌었습니다.양쪽 콜레이션이 다른 외래키 — 둘 중 하나라도 비결정 콜레이션이면 거부됩니다(
42P21). 2.17은 만들어 주었습니다. 양쪽이 같은 비결정 콜레이션이면 지금도 됩니다. 서로 다른 결정 콜레이션 둘도 됩니다.NOT VALID로도 미룰 수 없고, 라벨 열에 건 외래키도 마찬가지로 거부됩니다. 이 항목은 애플리케이션만의 문제가 아닙니다. 2.17 덤프를 복원하면 그 테이블이 제약 없이 만들어집니다. 업그레이드 전에 해당 쌍을 찾으십시오 — 비결정 콜레이션이 낀 외래키를 보십시오.
비결정 콜레이션이 낀 외래키#
덤프하거나 업그레이드하기 전에, 2.17 클러스터의 데이터베이스마다 다음을 실행하십시오.
SELECT c.conrelid::regclass AS referencing, c.conname, fa.attname AS col,
fc.collname AS referencing_collation, pc.collname AS referenced_collation
FROM pg_constraint c
CROSS JOIN LATERAL unnest(c.conkey, c.confkey) AS k(fkatt, pkatt)
JOIN pg_attribute fa ON fa.attrelid = c.conrelid AND fa.attnum = k.fkatt
JOIN pg_attribute pa ON pa.attrelid = c.confrelid AND pa.attnum = k.pkatt
JOIN pg_collation fc ON fc.oid = fa.attcollation
JOIN pg_collation pc ON pc.oid = pa.attcollation
WHERE c.contype = 'f'
AND fa.attcollation <> pa.attcollation
AND NOT (fc.collisdeterministic AND pc.collisdeterministic);
나오는 행 하나하나가 2.18이 거부할 제약입니다. 2.17에서 두 열의 콜레이션을 같게 맞춘 다음 덤프하십시오. 조건은 서버가 적용하는 조건 그대로이고 서버가 읽는 카탈로그 열을 그대로 읽으므로, 업그레이드가 거부할 제약보다 더 많이도 더 적게도 고르지 않습니다.
경고
어느 경로도 미리 알려 주지 않습니다. pg_upgrade --check는 *Clusters are compatible*로 끝나고,
업그레이드는 그 제약을 다시 만드는 자리에서 실패합니다. 덤프·복원은 더 나쁩니다. 복원이 성공했다고
보고하고 테이블은 외래키 없이 들어오며, 그 뒤로는 아무것도 참조하지 않는 행이 통과합니다.
경로 1. pg_upgrade 쓰기#
pg_upgrade는 새 클러스터의 카탈로그를 만든 다음 기존 사용자 데이터 파일을 재사용하므로 데이터를
다시 쓰지 않습니다. 그래프는 평범한 스키마와 테이블로 저장되므로, 그래프 데이터도 관계형 데이터와
똑같이 옮겨 갑니다.
시작하기 전에#
2.18을 별도의 위치에 설치하십시오. 2.17 설치본을 덮어쓰지 마십시오.
pg_upgrade에는 두 바이너리가 모두 필요하고, 2.17을 그대로 두는 것이 되돌아갈 길을 만들어 줍니다.디스크 공간. 기본적으로 데이터 파일을 복사하므로 두 번째 사본을 둘 자리가 필요합니다.
--link는 대신 하드 링크를 겁니다. 거의 즉시 끝나고 공간도 거의 들지 않지만, 두 데이터 디렉터리가 한 파일시스템에 있어야 하고 새 서버가 기동한 뒤에는 되돌릴 수 없게 됩니다.2.17 클러스터가 쓰는 외부 모듈을 2.18 설치본에도 똑같이 설치하십시오. 예를 들어
pgvector입니다. AgensGraph 자신의 그래프 기능은 서버에 내장돼 있으므로 다시 만들 그래프 확장은 없습니다.평범한 컬럼을 지닌 레이블이 업그레이드를 막습니다.
pg_upgrade는pg_dump --binary-upgrade에 일을 넘기는데, 그것은id·start·end·properties말고 다른 컬럼을 가진 그래프 레이블을, 물리적 컬럼 배치를 조용히 망가뜨리는 대신 거부합니다. 시작하기 전에 찾아 두십시오:SELECT c.relname, a.attname FROM pg_catalog.ag_label l JOIN pg_class c ON c.oid = l.relid JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum > 0 AND NOT a.attisdropped WHERE a.attname NOT IN ('id', 'start', 'end', 'properties');
업그레이드하기 전에 그 컬럼들을 지우거나 데이터를 다른 곳으로 옮기십시오.
모든 명령은 데이터 디렉터리를 소유한 운영체제 사용자로 실행하십시오.
아래 명령은 다음 변수를 씁니다:
export OLD=/usr/local/agensgraph-2.17
export NEW=/usr/local/agensgraph-2.18
export OLDDATA=$OLD/data
export NEWDATA=$NEW/data
1단계. 옛 서버 정지#
pg_upgrade가 도는 동안 두 클러스터 모두 내려가 있어야 합니다.
$OLD/bin/ag_ctl -D $OLDDATA stop
2단계. 새 클러스터 초기화#
옛 클러스터와 같은 슈퍼유저·인코딩·로케일을 쓰고, 데이터 체크섬 설정도 맞추십시오.
$NEW/bin/initdb -D $NEWDATA -U postgres --encoding=UTF8 --no-data-checksums
경고
대부분의 업그레이드에서 --no-data-checksums는 선택 사항이 아닙니다. PostgreSQL 18은 데이터
페이지 체크섬을 기본으로 켜고 PostgreSQL 17은 껐습니다. 그러므로 2.17 클러스터를 -k로 초기화하지
않았다면 두 클러스터가 어긋나고, pg_upgrade는 아무것도 하기 전에 멈춥니다:
Performing Consistency Checks
-----------------------------
Checking cluster versions ok
old cluster does not use data checksums but the new one does
Failure, exiting
초기화하기 전에 어느 쪽인지 확인하십시오:
$OLD/bin/pg_controldata -D $OLDDATA | grep checksum
Data page checksum version: 0으로 나오면 --no-data-checksums를 주십시오. 1로 나오면 그
플래그를 빼십시오. 체크섬을 켜는 것은 별개의 작업이며
(pg_checksums 참고) 할 만한 일이지만,
업그레이드의 일부로 하지 말고 그 뒤에 하십시오.
3단계. 호환성 확인#
--check는 두 클러스터를 검사하며 아무것도 바꾸지 않습니다.
$NEW/bin/pg_upgrade \
-b $OLD/bin -B $NEW/bin \
-d $OLDDATA -D $NEWDATA \
-U postgres --check
검사가 성공하면 *Clusters are compatible* 로 끝납니다.
경고
검사를 통과했다고 업그레이드가 성공한다는 뜻은 아닙니다. 이 검사는 비결정 콜레이션이 낀 외래키를 찾지 않으며, 4단계는 그 제약을 다시 만드는 자리에서 실패합니다. 위 질의를 직접 실행하십시오.
데이터베이스 슈퍼유저를 -U로 주십시오. 기본적으로 pg_upgrade는 운영체제 사용자로 접속하는데,
그것은 보통 데이터베이스 롤이 아닙니다.
4단계. 업그레이드 실행#
--check만 뺀 같은 명령입니다:
$NEW/bin/pg_upgrade \
-b $OLD/bin -B $NEW/bin \
-d $OLDDATA -D $NEWDATA \
-U postgres
Upgrade Complete로 끝납니다. 데이터 파일을 복사하는 대신 하드 링크하려면 검사와 업그레이드
양쪽에 --link를 더하십시오.
5단계. 새 서버 기동#
$NEW/bin/ag_ctl -D $NEWDATA -l $NEW/logfile start
새 서버에 붙어 있는지, 그리고 그래프가 넘어왔는지 확인하십시오:
SELECT version();
SET graph_path = <your graph>;
MATCH (n) RETURN count(n);
6단계. 업그레이드 뒤에 할 일#
이 중 셋은 AgensGraph에만 해당하며, 어느 것도 선택 사항이 아닙니다.
통계를 다시 만드십시오. pg_upgrade는 옵티마이저 통계를 가져오지 않으므로, 다시 만들기
전까지 계획이 나쁩니다:
$NEW/bin/vacuumdb -U postgres --all --analyze-in-stages
그래프 메타데이터를 다시 수집하십시오. ag_graphmeta가 플래너의 스캔 쳐내기를 이끕니다.
바이너리 업그레이드는 그것을 빈 채로 두고 그래프를 무효로 표시하므로, 그래프마다 한 번씩 다시
만들기 전까지 쳐내기가 꺼져 있습니다:
SET graph_path = <your graph>;
SELECT regather_graphmeta();
반영됐는지 확인하십시오:
SELECT graphname, graphmeta_valid FROM pg_catalog.ag_graph;
간선 레이블의 통계를 다시 조정하십시오. 2.18은 새 간선 레이블의 start·end 컬럼에 대한
통계 목표치를 10000에서 1000으로 낮췄습니다. 2.17에서 만든 레이블은 옛 값을 그대로 지녀 간선 조인
때마다 큰 계획 비용 — 큰 레이블에서는 수백 밀리초 — 을 치릅니다. 간선 레이블마다 이렇게
하십시오:
ALTER TABLE <graph>.<elabel> ALTER COLUMN start SET STATISTICS 1000;
ALTER TABLE <graph>.<elabel> ALTER COLUMN "end" SET STATISTICS 1000;
ANALYZE <graph>.<elabel>;
그런 다음 업그레이드한 클러스터가 잘 도는 것을 확인했으면, pg_upgrade를 실행한 디렉터리에 그것이
써 둔 스크립트로 옛 데이터 파일을 지우십시오:
./delete_old_cluster.sh
되돌리기#
복사 모드에서, 그리고 delete_old_cluster.sh를 실행하기 전이라면 2.17 데이터 디렉터리는 그대로
있습니다. 새 서버를 정지하고 옛 서버를 기동하십시오:
$NEW/bin/ag_ctl -D $NEWDATA stop
$OLD/bin/ag_ctl -D $OLDDATA -l $OLD/logfile start
--link 업그레이드 뒤에는 두 클러스터가 데이터 파일을 공유하므로, 새 서버가 기동한 뒤에는 되돌릴
수 없습니다. 백업에서 복원하십시오.
경로 2. 덤프하고 다시 적재하기#
더 느리지만 모든 것을 다시 쓰고, 실행 중에 바이너리 사본을 둘씩 두지 않아도 됩니다.
$OLD/bin/pg_dumpall -U postgres -f cluster.sql
# start the 2.18 cluster, then:
$NEW/bin/psql -U postgres -d postgres -f cluster.sql
경고
psql은 오류가 나도 멈추지 않고, 그러고도 종료 코드 0 을 냅니다. 새 서버가 거부하는 것은 —
예를 들어 비결정 콜레이션이 낀
외래키 — 출력 한 줄로 지나가고
복원은 그것 없이 계속됩니다. 복원을 믿기 전에 로그를 읽으십시오.
복원이 멈추게 하려면 롤과 데이터를 따로 덤프하십시오. 롤 부분은 ON_ERROR_STOP으로 복원할 수
없습니다. pg_dumpall은 이미 새 클러스터에 있는 부트스트랩 슈퍼유저의 CREATE ROLE을 쓰고,
--clean --if-exists는 접속 중인 롤의 DROP ROLE로 실패 지점을 옮길 뿐입니다.
$OLD/bin/pg_dumpall -U postgres --globals-only -f globals.sql
$OLD/bin/pg_dump -U postgres -Fc -d mydb -f mydb.dump # once per database
# start the 2.18 cluster, then:
$NEW/bin/psql -U postgres -d postgres -f globals.sql # roles; errors here are benign
$NEW/bin/createdb -U postgres mydb
$NEW/bin/pg_restore -U postgres --exit-on-error -d mydb mydb.dump
알아 둘 것 둘입니다:
복원에
enable_graph_ddl이 필요할 수 있습니다. 평범한 컬럼을 지닌 레이블의 덤프는 자기ALTER TABLE … ADD COLUMN문장 둘레에SET enable_graph_ddl = on을 내보냅니다. 그 설정은 어느 롤이든 쓸 수 있으므로 평범한 사용자도 복원할 수 있습니다. 그 롤에ALTER ROLE … SET으로 강제로 꺼 두지 않았다면 말입니다.위의 그래프 메타데이터와 통계 작업은 여기서도 그대로 적용됩니다.
다운그레이드는 지원하지 않는다#
어떤 그래프든 승격된 컬럼을 쓰고 있으면 2.18 덤프는 2.17에
복원되지 않습니다. 덤프에 2.17 파서가 거부하는 CREATE VLABEL 형태가 들어 있고, 평문 스트림에서는
그 문장 뒤의 모든 것이 유실됩니다. 되돌아갈 길이 필요하다면 업그레이드 전에 받아 둔 2.17 백업을
보관하십시오.
pg_dump와 pg_restore가 AgensGraph 버전을 검사하지 않는다는 점도 유의하십시오. PostgreSQL의
server_version 범위 검사만 적용됩니다. 그래서 어긋남은 앞에서 거부되는 대신 복원 도중의 파싱
실패로 드러납니다.
실제 예제#
업그레이드 실습은 작은 클러스터에서 실제 명령과 출력으로 전체 절차를 돌려 봅니다.