OpenSource-Hub

pgrust

애플리케이션

malisper/pgrust

Rust로 PostgreSQL을 재작성하여 모든 회귀 테스트를 통과했습니다.

개요

pgrust는 Rust로 재작성된 PostgreSQL 데이터베이스 시스템으로, Postgres 18.3과 호환되며, 4.6만 개 이상의 회귀 쿼리를 통과했고, 디스크 형식이 네이티브 Postgres와 호환됩니다. 이 프로젝트의 목표는 Rust와 AI 보조 개발을 통해 Postgres 수정의 진입 장벽을 낮추는 것입니다.

README 미리보기

pgrust\n\n\n  A Postgres rewrite in Rust.\n\n\n\n  \n  \n  \n    \n  \n\n\n\n  Browser demo\n    |  \n  Discord\n    |  \n  Get pgrust updates\n    |  \n  Issues\n\n\n\n\npgrust targets compatibility with Postgres 18.3 and matches Postgres's\nexpected output across more than 46,000 regression queries.\n\npgrust is disk compatible with Postgres and can boot from an existing Postgres\n18.3 data directory.\n\nThe goal is to make Postgres easier to change from the inside: keep the behavior\nPostgres-shaped, keep the real Postgres tests as the oracle, and use Rust plus\nAI-assisted programming to explore deeper server changes.\n\nUpdate: We're working on a new not yet published version of pgrust that currently passes 100% of Postgres regression suite, has a thread per connection model instead of process per connection, is 50% faster than Postgres on transaction workloads, and is ~300x faster than Postgres on analytical workloads (2x slower than Clickhouse on clickbench and we think it can get faster than Clickhouse). Follow pgrust or join our Discord for updates!\n\n## Follow pgrust\n\n[Get project updates by email](https://pgrust.com/#updates), including new\nreleases, compatibility milestones, and architecture experiments.\n\n## Status\n\npgrust is not production-ready yet. It is not performance optimized yet.\n\nExisting Postgres extensions and procedural language extensions such as\nPL/Python, PL/Perl, and PL/Tcl are not generally compatible yet. Some bundled\ncontrib modules are already ported, and more compatibility may be possible over\ntime.\n\n## Roadmap\n\n- multithreaded Postgres internals\n- built-in connection pooling\n- better JSON-heavy workload support\n- fast forking and branching workflows\n- storage experiments, including no-vacuum designs\n- runtime guardrails for bad queries and AI-generated SQL\n- fewer sudden bad plan switches\n\n## Try It\n\nTry the WebAssembly demo at https://pgrust.com.

FAQ (5)

문제 해결
pgrust에서 크래시 복구 후 DROP TABLE이 CPU 100% 상태로 멈추는 문제를 해결하는 방법은?

이 문제는 WAL redo 과정에서 유출된 버퍼 핀 때문에 발생합니다. recovery prefetcher의 io_uring 레인이 마지막으로 프리페치된 페이지를 startup 스레드의 링 슬롯에 고정된(pinned) 상태로 남겨두며, InvalidateBuffer가 그 foreign pin을 기다리며 스핀하면서 취소할 수 없게 됩니다.

해결 방법: PR #2062, 커밋 4f84297963e(xlogrecovery: drain prefetch pins after the redo loop)가 포함된 빌드로 pgrust를 업그레이드하십시오. 이 패치는 redo 루프 직후, end-of-recovery 체크포인트 이전에 prefetch 링을 드레인하고, foreign-pin 대기를 취소 가능하게 만듭니다. 다음과 같이 빌드하고 재시작하십시오:

git fetch origin
git checkout 4f84297963e   # or any later commit containing the fix
cargo build --release --locked --bin postgres

그런 다음 서버를 재시작하고 DROP TABLE을 다시 시도하십시오. 복구 후에는 pg_buffercache에서 pinning_backends = 0인지 확인하여 해당 릴레이션에 유출된 핀이 없는지 검증하십시오.

취약한 빌드에서의 임시 완화 조치: 계획된 중지 전에 대량 삽입 이후 CHECKPOINT를 실행하여, 복구 중 해당 페이지가 WAL로부터만 재생되지 않도록 하십시오. 이 방법은 예기치 않은 크래시로부터는 보호해 주지 않습니다. 백엔드가 이미 스핀 상태에 들어갔다면 pg_cancel_backend로는 중지할 수 없으므로, 패치된 빌드로 재시작하십시오.

원본 Issue #93
문제 해결
pgrust에서 PostgreSQL IDENTITY 컬럼 테이블에 INSERT할 때 EXPLAIN VERBOSE를 실행하면 발생하는 "T_NextValueExpr deparse arm unported" 오류를 어떻게 해결하나요?

이 문제는 pgrust 0.2에서 EXPLAIN VERBOSE가 GENERATED ALWAYS AS IDENTITY 컬럼의 플랜을 디파스할 때 발생합니다. 즉시 적용 가능한 해결 방법: VERBOSE 없이 EXPLAIN을 실행하세요. 예를 들면:

EXPLAIN INSERT INTO t (v) VALUES (1);

다른 옵션을 사용할 때도 VERBOSE를 생략할 수 있습니다:

EXPLAIN (ANALYZE, BUFFERS) INSERT INTO t (v) VALUES (1);

플랜은 출력되지만, identity 시퀀스의 nextval(...) 표현식이 포함된 verbose Output: 줄은 생략됩니다.

영구적인 해결 방법: PR #472가 포함된 빌드로 pgrust를 업그레이드하세요(main에서 수정됨, 2026-08-08). 이 수정은 NextValueExpr를 nextval('seq')로 디파스하여 PostgreSQL 18.6과 일치합니다. serial 컬럼은 일반적인 DEFAULT nextval(...) 경로를 사용하므로 영향을 받지 않습니다.

원본 Issue #111
문제 해결
pgrust에서 format()에 NULLIF, GREATEST, IS NULL 또는 AND를 전달할 때 발생하는 "funcapi exprType: node family T_NullIfExpr not ported" 오류를 어떻게 해결하나요?

커밋 77ab13c454b를 포함하는 최신 main 빌드로 pgrust를 업그레이드하십시오. 이 수정은 funcapi가 인자 타입 해석을 nodes_core::node_funcs::expr_type에 위임하도록 하며, T_NullIfExpr, T_MinMaxExpr, T_NullTest, T_BoolExpr, T_DistinctExpr, T_BooleanTest, T_ScalarArrayOpExpr, T_SubPlan 및 관련 표현식 계열을 다룹니다. 이는 PostgreSQL 18.3 호환 코드를 포함하는 pgrust 0.2와, format(), concat(), concat_ws(), json_build_object()와 같이 런타임에 해석되는 "any" 또는 VARIADIC "any" 인자를 사용하는 함수에 영향을 미칩니다. 즉시 업그레이드가 불가능한 경우, 문제가 되는 표현식을 구체화된 CTE 또는 서브쿼리에서 평가하여, 원시 표현식 대신 결과 컬럼/Var를 함수에 전달하십시오.

원본 Issue #109
문제 해결
SERIALIZABLE 트랜잭션을 시작할 때 발생하는 "SERIALIZABLEXACT slots exhausted and the pg_serial summarization path is not ported" 패닉을 해결하는 방법

이 패닉은 크기가 (MaxBackends + max_prepared_xacts) * 10으로 고정된 SERIALIZABLEXACT 풀이 가득 찼을 때 발생합니다. 영향을 받는 pgrust 빌드에서는 pg_serial SLRU 요약(summarization)이 구현되지 않았기 때문에, GetSerializableTransactionSnapshot이 가장 오래된 커밋된 serializable 트랜잭션을 재활용하는 대신 패닉을 일으켰습니다.

해결 방법은 PR #168이 포함된 최신 main 빌드로 업그레이드하는 것입니다. 이 PR은 실제 pg_serial SLRU를 이식하고, GetSerializableTransactionSnapshotInt가 SummarizeOldestCommittedSxact와 CreatePredXact를 반복 실행하도록 만들어 PostgreSQL의 동작과 일치시킵니다. SerialAdd, SerialSetActiveSerXmin, CheckPointPredicate도 함께 구현되었습니다.

단계:
1. PR #168이 포함된 main 커밋을 가져와 빌드합니다.
2. 데이터베이스를 재배포하고 재시작합니다.
3. 선택적으로 scripts/ssi-sxact-exhaustion-e2e.sh를 사용해 검증합니다. 이 회귀 테스트는 슬롯 풀을 고갈시키고 CHECKPOINT를 실행한 뒤 패닉이 발생하지 않고 서버가 정상 상태를 유지함을 확인합니다.

이전 빌드에서의 임시 완화 조치:
- SERIALIZABLE 트랜잭션의 동시성이나 커밋 속도를 줄입니다.
- SxactGlobalXmin을 고정하는 장기 실행 SERIALIZABLE 세션을 피합니다.
- 안전한 경우 max_prepared_transactions 또는 MaxBackends 값을 늘려 풀 임계값을 높인 다음 재시작합니다.
- 정확성 요구사항이 허용하는 경우에만 변경이 빈번한 트랜잭션을 READ COMMITTED로 전환합니다. 이는 serializable 보장을 약화시킵니다.

원본 Issue #61
문제 해결
coverage-guard 트립 후 pgrust 병렬/morsel VACUUM에서 발생하는 dead_items_info.num_items 이중 계산 또는 디버그 어설션 실패를 해결하려면 어떻게 해야 하나요?

이 버그는 PGRUST_RUNTIME_VACUUM=1로 활성화되는 실험적 parallel/morsel VACUUM 경로에 영향을 줍니다. 커버리지 가드가 resume_g를 되감았을 때, 리더가 serial arm이 해당 페이지를 다시 스캔하기 전에 재개 지점보다 위에 있는 지연 정리(deferred-cleanup) 페이지를 처리할 수 있었습니다. dead_items_add()는 블록의 TIDs를 교체하면서도 dead_items_info.num_items를 다시 증가시켜 이중 카운트를 유발했고, 디버그 빌드에서 debug_assert_eq!(tids.len() as i64, vacrel.dead_items_info.num_items)를 트리거했습니다.

수정: PR #469/현재 main이 포함된 pgrust 빌드로 업데이트하십시오. 이 수정은 round_drain_plan이 리더 지연 정리 페이지를 되감은 재개 블록 아래로 제한(clamp)하도록 하여, 각 페이지가 하나의 arm에서만 드레인되도록 보장합니다. 회귀 테스트에는 morsel_coverage_trip_counts_each_dead_item_once와 morsel_verified_round_drains_all_runs_and_deferred가 포함됩니다.

임시 해결 방법: 실험적 병렬 vacuum 경로를 비활성화하십시오:

unset PGRUST_RUNTIME_VACUUM
# 또는
PGRUST_RUNTIME_VACUUM=0

프로덕션에서는 PGRUST_RUNTIME_VACUUM_FAULT=lose-local과 같은 테스트 폴트 인젝션을 활성화하지 마십시오.

원본 Issue #66