버전 번호가 하나 비어 있으면 신경이 쓰여요. 8월 13일에 나온 PostgreSQL 마이너 릴리스는 18.6인데, 그 앞은 18.5가 아니라 18.4입니다. 제 경우엔 패키지 목록을 보다가 “내가 하나 놓쳤나” 싶어 한참을 되짚었습니다. 결론부터 적으면 놓친 것은 없습니다. 18.5는 만들어졌지만 세상에 나오지 않았습니다.
공식이 말한 것은 한 줄뿐입니다
사유를 언급한 곳은 두 군데인데, 표현이 미묘하게 다릅니다.
18.6 릴리스 노트에는 이렇게 적혀 있습니다.
18.5 was never released, due to a regression discovered post-wrap.
릴리스 공지는 좀 더 건조합니다.
This release skips PostgreSQL 18 versions from PostgreSQL 18.4 to 18.6. 18.5 was not shipped due to a regression.
공지는 “shipped"라고만 했고, 릴리스 노트는 post-wrap이라는 단어를 하나 더 얹었습니다. 이 단어가 사실상 전부를 설명합니다. 무엇이 wrap이고, 그 이후라는 게 왜 중요한지 알면 18.5가 사라진 경로가 그대로 보입니다.
마이너 릴리스는 이런 순서로 만들어집니다
PostgreSQL의 Release process 위키에 절차가 공개돼 있습니다. 요약하면 committer가 버전을 찍고, 서버에서 tarball을 말고, packager들이 먼저 써 보고, 마지막에 태그를 미는 순서입니다.
flowchart TD
A["version_stamp.pl
Stamp 18.5"]
B["mk-release-bundle
tarball 생성"]
C["packager
예비 테스트 24시간+"]
D["git tag
REL_18_5"]
E["공개 발표"]
X["회귀 발견"]
F["코드 수정"]
G["Stamp 18.6
다시 wrap"]
A --> B
B --> C
C --> D
D --> E
C -. 문제 발생 .-> X
X --> F
F --> G
G --> C
2단계가 wrap입니다. pgsql 계정으로 borka.postgresql.org에 들어가 mk-release-bundle을 실행하면 tarball과 체크섬이 staging 디렉토리에 만들어집니다. 이 단계를 특정 서버에서만 하는 이유는 재현성 때문입니다. bison, flex, docbook 버전이 다르면 결과물이 달라지니 빌드 환경을 한 곳으로 고정해 둔 것입니다.
주목할 곳은 3단계와 4단계 사이입니다. 위키가 태그를 두고 분명하게 적어 뒀습니다.
Pushing a tag is more or less irreversible, so don’t do this until packager preliminary testing is over.
태그를 밀면 되돌리기 어렵습니다. 그래서 packager들이 최소 24시간 먼저 만져 보고, 이상이 없어야 태그가 나갑니다. 18.5는 그 구간을 통과하지 못했습니다.
취소는 되는데 번호는 돌아오지 않습니다
같은 위키에 사고 처리 절차도 한 줄로 적혀 있습니다.
In event of disaster, fix code as needed then repeat the wrap process, with or without a version number bump as seems appropriate.
문제가 생기면 코드를 고쳐 wrap을 다시 하되, 번호를 올릴지 말지는 그때 적절히 판단하라는 뜻입니다. 규정이 아니라 재량입니다. 18.5 건에서는 올리는 쪽을 택했습니다.
왜 그랬을까요. version_stamp.pl이 이미 Stamp 18.5. 커밋을 남겼고 그 번호로 tarball이 만들어졌기 때문입니다. staging에 있던 물건이라 일반 사용자에게 내려간 것은 아니지만, packager들 손에는 18.5라는 이름표가 붙은 파일이 이미 가 있었습니다. 같은 번호로 내용이 다른 tarball을 한 번 더 돌리는 것보다 번호를 하나 올리는 편이 안전합니다. 태그를 밀기 전이라 릴리스 자체는 멈출 수 있었지만, 번호는 그 시점에 이미 쓰인 것입니다.
8월 9일까지는 18.5였습니다
타임라인도 이 해석과 맞습니다. Jonathan Katz(조너선 카츠)가 pgsql-hackers에 올린 8월 13일 릴리스 공지 초안은 2026년 8월 9일자인데, 거기 적힌 버전은 아직 18.5입니다.
마이너 릴리스는 관례상 목요일에 공개하고 tarball은 그 주 초에 맙니다. 8월 13일이 목요일이니 wrap은 10일 전후, 공지 초안은 그 직전에 돌린 셈입니다. 초안이 나가고 며칠 사이에 번호가 하나 올라갔습니다.
결번은 여섯 개뿐입니다
그럼 이런 일이 자주 있었을까요. 세어 봤습니다. bucardo가 모든 버전의 릴리스 노트를 한 페이지에 모아 두는데, 여기서 never released를 전수 검색하면 여섯 건이 나옵니다.
| 결번 | 직전 릴리스 | 대체 릴리스 |
|---|---|---|
| 7.4.20 | 7.4.19 (2008-01-07) | 7.4.21 (2008-06-12) |
| 8.0.16 | 8.0.15 (2008-01-07) | 8.0.17 (2008-06-12) |
| 8.1.12 | 8.1.11 (2008-01-07) | 8.1.13 (2008-06-12) |
| 8.2.8 | 8.2.7 (2008-03-17) | 8.2.9 (2008-06-12) |
| 8.3.2 | 8.3.1 (2008-03-17) | 8.3.3 (2008-06-12) |
| 18.5 | 18.4 (2026-05-14) | 18.6 (2026-08-13) |
여섯 개지만 사건은 두 건입니다. 위의 다섯은 대체 릴리스 날짜가 전부 2008년 6월 12일로 같습니다. 한 번의 사고로 당시 지원하던 브랜치가 통째로 결번된 것입니다.
18.5는 혼자입니다. 같은 날 나온 17.11, 16.15, 15.19, 14.24는 번호가 정상입니다. 회귀가 18 브랜치에만 있었다는 뜻입니다.
2008년에는 무슨 일이 있었나
8.3.2 릴리스 노트를 열면 Release Date 필드가 never released입니다. 그런데 본문은 멀쩡합니다. “This release contains a variety of fixes from 8.3.1"로 시작하고, Migration to Version 8.3.2 절도 붙어 있고, Changes 목록에 마흔 건 가까운 수정이 그대로 나열돼 있습니다. Windows에서 UTF-8 인코딩일 때 나던 크래시, %r 매크로의 archive 절단 지점 오산, GIN의 “too many LWLocks taken” 실패, SIGTERM으로 backend를 개별 종료했을 때 shared memory가 오염되던 문제가 보입니다.
그중 %r 항목은 지금 봐도 아찔합니다. warm standby 스크립트가 그 값을 믿고 WAL segment 파일을 버리면 데이터를 잃을 수 있었습니다. 이런 수정을 담은 릴리스가 문턱까지 갔다가 멈췄습니다.
노트에 사유는 적혀 있지 않습니다. 대신 대체 버전 노트의 첫 문장이 단서를 흘립니다.
| 버전 | 첫 문장 |
|---|---|
| 8.3.3 | one serious and one minor bug fix over 8.3.2 |
| 8.2.9 | one serious and one minor bug fix over 8.2.8 |
| 7.4.21 | one serious bug fix over 7.4.20 |
세상에 나온 적 없는 버전을 기준점으로 삼아 “그 대비 몇 건"이라고 적었습니다. 결번본이 실재했다는 자백입니다. 그리고 여기서 말하는 “one serious"가 무엇인지는 다섯 브랜치 공통 항목으로 노트에 남아 있습니다.
Make
pg_get_ruledef()parenthesize negative constants (Tom Lane)Before this fix, a negative constant in a view or rule might be dumped as, say,
-42::integer, which is subtly incorrect: it should be(-42)::integerdue to operator precedence rules. Usually this would make little difference, but it could interact with another recent patch to cause PostgreSQL to reject what had been a valid SELECT DISTINCT view query. Since this could result in pg_dump output failing to reload, it is being treated as a high-priority fix.
view나 rule 안에 들어 있는 음수 상수를 괄호 없이 덤프하던 문제입니다. 연산자 우선순위상 (-42)::integer여야 하는데 -42::integer로 나왔습니다. 그 자체로는 대개 차이가 없지만, 당시 함께 들어간 다른 패치와 맞물리면 멀쩡하던 SELECT DISTINCT view 쿼리를 PostgreSQL이 거부했습니다.
여기서 심각도가 뛴 지점은 마지막 문장입니다. pg_dump 출력이 다시 적재되지 않을 수 있다는 결론이었습니다. 백업 파일이 복원되지 않는 문제는 다른 어떤 버그와도 무게가 다릅니다. 준비돼 있던 다섯 개 tarball을 버리고 이 수정을 얹어 다시 낸 이유로 충분합니다.
두 사건이 남긴 기록의 차이
구조는 같습니다. wrap이 끝난 뒤 회귀가 잡혔고, 고쳐서 번호를 올려 다시 냈습니다. 달라진 것은 그 사실을 어떻게 적어 두느냐입니다.
18.6 노트는 결번 사유를 한 줄로 명시했습니다. 짧지만 왜 번호가 비었는지가 문서 안에 적혀 있습니다. 2008년 노트들은 never released라는 사실만 남기고 사유를 적지 않았습니다. 지금 그 이유를 재구성할 수 있는 것은 대체본이 “over 8.3.2"라는 표현을 쓴 덕분입니다. 의도한 기록이라기보다 흔적에 가깝습니다.
공통점도 있습니다. 여섯 개 전부 릴리스 노트 페이지가 지금도 살아 있습니다. 나오지 않은 버전의 문서를 지우지 않는 관행이 적어도 2008년부터 이어지고 있습니다. 덕분에 18년 전 사건을 1차 출처로 따라갈 수 있었습니다.
검색하면 섞여 나오는 이야기 하나
18.5 결번을 검색하면 “standby가 구버전 마이너의 WAL을 재생하다 self-deadlock에 빠진다"는 내용이 사유처럼 딸려 나옵니다. 별개 사건입니다.
credativ가 정리한 그 버그는 MultiXactOffsetSLRU deadlock이고, 2026년 5월 14일에 나온 14.23, 15.18, 16.14에서 유입됐습니다. 17과 18은 영향이 없습니다. 증상은 standby의 startup 프로세스가 pg_stat_activity에서 LWLock/MultiXactOffsetSLRU 대기로 멈추는 형태입니다.
같은 8월 13일 릴리스에서 함께 고쳐졌을 뿐, 18.5를 취소시킨 원인이 아닙니다. 두 이야기를 붙여 쓰면 틀린 글이 됩니다.
지금 확인할 것
운영 관점에서 할 일은 많지 않습니다.
- 18.4에서 18.6으로 바로 올립니다. 중간에 빠뜨린 버전은 없습니다
- 자동화 스크립트가 마이너 번호를 순차 증가로 가정하고 있다면 확인합니다.
18.4 + 1 = 18.5를 기대하는 코드는 여기서 멈춥니다 - 사내 문서나 지원 버전 표에 18.5를 적어 둔 곳이 있으면 지웁니다
3번은 사소해 보이지만 실제로 혼란을 만듭니다. “18.5 적용 예정"이라고 써 둔 계획서가 남아 있으면 나중에 읽는 사람이 없는 버전을 찾게 됩니다.
남은 질문
18.5를 취소시킨 회귀가 정확히 무엇이었는지는 공개되지 않았습니다. 공식 문구는 “a regression"이 전부입니다. 2008년 사건에서도 회귀를 유발한 “another recent patch"가 무엇인지는 노트에 적혀 있지 않습니다.
저는 이 공백이 문제라고 보지는 않아요. 세상에 나가지 않은 코드의 버그를 상세히 적는 것은 그 자체로 이상한 일이니까요. 다만 번호가 하나 비면 사람은 반드시 이유를 찾습니다. 18.6 노트가 한 줄이라도 남겨 둔 덕분에 저 같은 사람이 패키지 목록 앞에서 오래 헤매지 않았습니다. 기록은 그 정도만 해 줘도 충분히 일을 합니다.
참고
- PostgreSQL 18.6 릴리스 노트 - “18.5 was never released, due to a regression discovered post-wrap”
- PostgreSQL 18.6, 17.11, 16.15, 15.19, 14.24 and 19 Beta 3 Released! - PostgreSQL News, 2026-08-13
- Release process - PostgreSQL wiki, wrap/tag 절차와 사고 처리
- Versioning Policy - 마이너 릴리스 주기와 번호 규칙
- Release 8.3.2 - Release Date가 never released인 노트
- Release 8.3.3 - “one serious and one minor bug fix over 8.3.2”
- Postgres Release Notes - All Versions - 결번 전수 조사에 사용
- 2026-08-13 release announcement draft - 8월 9일 시점 표기는 18.5
- Replication Deadlock Bug in Current Postgres Releases 14-16 - credativ, 18.5 결번과는 별개 사건