동시성·보안·운영
DuckDB의 단일 프로세스 write 모델, read-only 공유, extension 보안, untrusted SQL 방어 기준을 정리합니다.
핵심 요약
- embedded 파일 직접 접근은 한 프로세스의 multi-thread write 또는 여러 프로세스의 read-only 공유를 사용합니다. 여러 client의 쓰기는 Quack 서버 경로와 구분합니다.
- DuckDB SQL은 파일·네트워크·extension에 접근하므로 untrusted SQL은 Bash/Python 코드처럼 보고 VM 격리, egress 제한, timeout, memory_limit로 방어합니다.
- extension은 parent process와 같은 권한으로 실행되므로 core-only 환경은 allow_community_extensions=false로 낮추고, 이 보안 설정은 세션 안에서 다시 느슨하게 되돌릴 수 없게 lock됩니다.
- CREATE SECRET의 SCOPE를 좁혀 환경별 prefix가 한 세션에 섞이지 않게 하고 persistent secret의 로컬 디스크 보관 위험을 문서화합니다.
2.0에서 구분할 동시성 경로
| 경로 | 쓰기 조정 위치 | 운영 의미 |
|---|---|---|
| embedded 파일 직접 접근 | 한 writer 프로세스 내부 | 여러 프로세스가 같은 파일을 직접 쓰는 설계를 피함 |
| Quack remote protocol | DuckDB 서버 프로세스 | 여러 클라이언트 프로세스가 서버를 통해 native DB 접근 |
| DuckLake + PostgreSQL catalog | 중앙 catalog | 레이크의 동시 read/write 조정은 별도 배포·운영 계약 |
아래 단일 프로세스 설명은 embedded 직접 파일 접근에 대한 것입니다. 2.0은 Quack을 통한 서버 경로를 지원합니다. 기본 localhost binding을 유지하고 원격 연결은 TLS reverse proxy·인증·네트워크 정책을 함께 설계합니다. 테스트용 직접 외부 노출 옵션을 운영 기본값으로 삼지 않습니다.
DuckDB 운영에서 가장 큰 오해는 "파일 DB니까 여러 앱이 동시에 쓰면 되겠지"입니다. DuckDB는 in-process 분석 엔진이라 동시성 모델도 이 전제 위에서 설계됐습니다. 보안도 DB 서버 권한 모델이 아니라 실행 프로세스 권한과 extension 권한으로 따져야 합니다.
Embedded 파일 직접 접근의 동시성 모델
| 상황 | 가능 여부 | 기준 |
|---|---|---|
| 한 프로세스 안 여러 thread read/write | 가능 | thread-local cursor 사용 |
| 여러 프로세스 read-only | 가능 | access_mode = 'READ_ONLY' |
| 여러 프로세스가 파일에 직접 write | 피함 | Quack 서버 경로 또는 별도 catalog 기반 조정 검토 |
| append 중심 thread write | 가능 | conflict와 transaction boundary 확인 |
| 같은 row update/delete 충돌 | 실패 가능 | optimistic concurrency conflict 처리 |
Python multi-thread에서는 원 connection에서 thread별 .cursor()를 만들어 사용합니다.
Untrusted SQL
DuckDB 공식 문서는 DuckDB SQL을 Bash나 Python 코드처럼 취급하라고 경고합니다. SQL은 파일을 읽고 쓰고 네트워크에 접근하며, extension을 로드하고 시스템 리소스를 소모합니다.
| 위협 | 방어 |
|---|---|
| 파일 유출 | container/VM 격리, OS 권한 최소화 |
| 네트워크 유출 | egress 제한, extension 제한 |
| CPU/메모리 DoS | timeout, threads, memory_limit |
| 디스크 고갈 | temp directory quota |
| extension 공급망 | core/community/unsigned policy |
Extension 보안
DuckDB extension은 DuckDB parent process와 같은 권한으로 실행됩니다. 기본값은 core/community signed extension을 허용하고,
core-only 환경이라면 allow_community_extensions = false로 낮춥니다. 보안 설정은 process 안에서 다시 느슨하게 되돌릴 수 없도록 lock됩니다.
SET allow_community_extensions = false;
SELECT name, value
FROM duckdb_settings()
WHERE name LIKE 'allow_%extensions%';unsigned extension은 개발·격리 환경이 아니면 허용하지 않습니다.
Secrets 운영
CREATE SECRET lake_s3 (
TYPE s3,
PROVIDER credential_chain,
SCOPE 's3://company-lake/curated/'
);secret scope를 좁혀 서로 다른 조직·환경 prefix가 같은 세션에서 섞이지 않게 합니다. persistent secret은 로컬 디스크 보관 위험을 문서화합니다.
운영 runbook
| 이벤트 | 조치 |
|---|---|
| extension update | staging job에서 재현성 테스트 후 pin 반영 |
| DuckDB minor upgrade | storage format, extension, client package release note 확인 |
| shared mart publish | staging prefix 검증 후 pointer 전환 |
| crash | WAL replay 확인, internal error면 process 재시작 |
| 권한 사고 | OS/cloud credential 회수, persistent secret 삭제 |
2.0 운영 inventory
writer·reader·Quack server/client의 버전, 확장 배포처와 공개키, 파일 storage version을 함께 기록합니다. core-only 정책에는 자체 저장소 제한도 포함합니다. 서버 접속이 성공해도 임의 SQL 실행 권한과 자원 예산이 검증된 것은 아닙니다.
복구 중인 DB의 WAL이나 프로세스가 사용하는 temp 파일은 지우지 않습니다. 실패 job의 산출물 정리는 소유 프로세스 종료와 복구·재처리 필요 여부를 확인한 뒤 수행합니다.