데이터베이스 시스템
Wippy는 PostgreSQL과 MySQL용 풀링 SQL 데이터베이스 엔트리와 단일 연결 SQLite 엔트리를 제공합니다.
이 페이지는 설정 레퍼런스입니다. 펜스에 version, namespace, entries가 모두
포함되지 않았다면 기존 엔트리 목록 안에 배치할 조각으로 취급하세요.
엔트리 종류
| 종류 | 설명 |
|---|---|
db.sql.postgres |
PostgreSQL 데이터베이스 |
db.sql.mysql |
MySQL 데이터베이스 |
db.sql.sqlite |
SQLite 데이터베이스 |
설정
표준 데이터베이스 (PostgreSQL, MySQL)
# src/data/_index.yaml
version: "1.0"
namespace: app.data
entries:
- name: main_db
kind: db.sql.postgres
host: "localhost"
port: 5432
database: "myapp"
username: "dbuser"
password: ${env:app.secrets:db_password}
pool:
max_open: 25
max_idle: 5
max_lifetime: "1h"
options:
sslmode: "disable"
lifecycle:
auto_start: true
SQLite
- name: cache_db
kind: db.sql.sqlite
file: "/var/data/cache.db" # Use :memory: for in-memory
pool:
max_open: 4
max_idle: 2
max_lifetime: "1h"
lifecycle:
auto_start: true
file: ":memory:")는 하나의 물리적 연결로 범위가 한정되므로 max_open과 max_idle이 1로 강제됩니다. 파일 기반 데이터베이스는 설정된 pool 값을 따르며, CDC 스냅샷 읽기 트랜잭션이 유일한 쓰기 연결을 점유하지 않으려면 이 설정이 필요합니다. 저널 모드는 항상 WAL입니다.
연결 필드
표준 데이터베이스 필드
| 필드 | 타입 | 설명 |
|---|---|---|
host |
string | 데이터베이스 호스트 주소 |
port |
int | 데이터베이스 포트 번호 |
database |
string | 데이터베이스 이름 |
username |
string | 데이터베이스 사용자 |
password |
string | 데이터베이스 비밀번호 |
pool |
object | 연결 풀 설정 |
options |
map | 데이터베이스별 옵션 |
lifecycle |
object | 라이프사이클 설정 |
SQLite 필드
| 필드 | 타입 | 기본값 | 설명 |
|---|---|---|---|
file |
string | 필수 | 데이터베이스 파일 경로 또는 :memory: |
pool |
object | - | 연결 풀 설정; :memory:에서는 max_open과 max_idle이 1로 강제됨 |
max_mutation_changes |
int | 100000 | 커밋된 변경 관찰자에서 한 트랜잭션이 보유할 수 있는 행 수 |
max_mutation_bytes |
int | 67108864 | 관찰자에서 한 트랜잭션이 보유할 수 있는 논리 바이트 수 (64 MiB) |
options |
map | - | 허용되지만 무시됨 |
lifecycle |
object | - | 라이프사이클 설정 |
max_mutation_changes와 max_mutation_bytes는 db.cdc.sqlite 소스에 데이터를 공급하는 인메모리 커밋 변경 관찰자의 한계를 정합니다. 두 필드 중 하나가 0이면 기본값이 선택되고, 음수 값은 거부됩니다. 이 한계는 정확하기보다 보수적입니다: SQLite는 pre-update 훅에 완전한 행을 전달하므로, 한계가 후보를 거부하기 전에 행 하나가 구체화될 수 있습니다.
시크릿 및 환경 값
${env:NAME} 플레이스홀더로 환경 레지스트리에서 연결 값을 가져오며, 디코드 시점에 해석됩니다. NAME은 등록된 변수의 공개 이름 또는 엔트리 ID(예: app.secrets:db_password)이며, 원시 OS 환경 변수가 아닙니다.
- name: prod_db
kind: db.sql.postgres
host: ${env:DB_HOST}
port: ${env:DB_PORT}
database: ${env:DB_NAME}
username: ${env:DB_USER}
password: ${env:app.secrets:db_password}
<field>_env 디렉티브(host_env, port_env, database_env, username_env, password_env)를 사용하며 동일하게 해석됩니다. 이 형식은 더 이상 권장되지 않습니다 — 위에 제시된 ${env:NAME} 플레이스홀더로 이전하세요.
env.variable 엔트리를 사용하세요. 안전한 시크릿 관리는 환경을 참조하세요.
연결 풀
연결 풀링 동작 설정. 풀 설정은 Go의 database/sql 연결 풀에 매핑됩니다.
| 필드 | 타입 | 기본값 | 설명 |
|---|---|---|---|
max_open |
int | 0 | 최대 열린 연결 (0 = 무제한) |
max_idle |
int | 0 | 최대 유휴 연결 (0 = 유휴 연결을 유지하지 않음) |
max_lifetime |
duration | 1h | 최대 연결 수명 |
pool:
max_open: 25 # Limit concurrent connections
max_idle: 5 # Keep 5 connections ready
max_lifetime: "30m" # Recycle connections every 30 minutes
max_idle을 max_open 이하로 설정하세요. max_lifetime을 초과하는 연결은 닫히고 교체되어 오래된 연결에서 복구하는 데 도움이 됩니다.
DSN 형식
각 데이터베이스 타입은 설정에서 DSN을 구성합니다. options가 있으면 키 순으로 정렬되어 뒤에 붙으며, 기본으로 포함되는 옵션은 없습니다.
PostgreSQL {id="dsn-postgresql"}
host='host' port=port user='username' password='password' dbname='database' [option='value' ...]
포트를 제외한 모든 값은 작은따옴표로 묶이고, 내부의 '와 \는 백슬래시로 이스케이프되므로, 공백이나 따옴표를 포함한 호스트, 비밀번호, 옵션 값이 그대로 전달됩니다.
MySQL {id="dsn-mysql"}
username:password@tcp(host:port)/database[?option=value&...]
SQLite {id="dsn-sqlite"}
file:/path/to/database.db?mode=rwc
:memory:
데이터베이스 옵션
일반적인 데이터베이스별 옵션:
PostgreSQL {id="options-postgresql"}
options:
sslmode: "require" # disable, require, verify-ca, verify-full
connect_timeout: "10" # Connection timeout in seconds
application_name: "myapp"
MySQL {id="options-mysql"}
options:
charset: "utf8mb4"
parseTime: "true" # Parse time values to time.Time
loc: "Local" # Timezone
SQLite {id="options-sqlite"}
SQLite는 options 맵을 DSN에 적용하지 않습니다. 파일 데이터베이스는 항상 mode=rwc로 열리며 저널 모드는 항상 WAL로 설정됩니다. options 필드는 허용되지만 무시됩니다.
예제
SSL을 사용하는 PostgreSQL
- name: secure_postgres
kind: db.sql.postgres
host: "db.example.com"
port: 5432
database: "production"
username: "app_user"
password: ${env:app.secrets:db_password}
pool:
max_open: 50
max_idle: 10
max_lifetime: "1h"
options:
sslmode: "verify-full"
sslcert: "/certs/client.crt"
sslkey: "/certs/client.key"
sslrootcert: "/certs/ca.crt"
lifecycle:
auto_start: true
MySQL 읽기 전용 복제본
- name: mysql_replica
kind: db.sql.mysql
host: "replica.db.example.com"
port: 3306
database: "app"
username: "readonly"
password: ${env:app.secrets:replica_password}
pool:
max_open: 20
max_idle: 5
max_lifetime: "30m"
options:
charset: "utf8mb4"
parseTime: "true"
readTimeout: "30s"
SQLite 인메모리
- name: test_db
kind: db.sql.sqlite
file: ":memory:"
여러 데이터베이스 구성
entries:
# Primary database
- name: users_db
kind: db.sql.postgres
host: ${env:USERS_DB_HOST}
port: 5432
database: "users"
username: ${env:USERS_DB_USER}
password: ${env:app.secrets:users_db_password}
lifecycle:
auto_start: true
# Analytics database
- name: analytics_db
kind: db.sql.mysql
host: ${env:ANALYTICS_DB_HOST}
port: 3306
database: "analytics"
username: ${env:ANALYTICS_DB_USER}
password: ${env:app.secrets:analytics_db_password}
lifecycle:
auto_start: true
# Local cache
- name: cache
kind: db.sql.sqlite
file: "/var/cache/app.db"
lifecycle:
auto_start: true
런타임 등록
레지스트리 모듈을 사용하여 런타임에 데이터베이스를 등록할 수 있습니다.
Lua API
쿼리, 트랜잭션, 연결 작업은 SQL 모듈을 참조하세요.