24. DB 운영 (MySQL)

Replication · Outbox · Idempotency · Partitioning · Retention

Replication 권장

DBMode이유
ledgerdbsemi-sync (loseless)자금 zero tolerance — rpl_semi_sync_master_wait_point=AFTER_SYNC
auditdbsemi-sync (loseless)audit defense — 1 row 손실 critical
approverdbsemi-sync 권장governance evidence
walletdbasync OK (semi-sync 권장)metadata
chaindbasync OKchain 자체에 있음 — re-fetch 가능
providerdbasync OKprovider 에서 re-ingest 가능
recondbasync OKreconciliation 자체가 evidence
필수 설정

자금 / 감사 DB 는 loseless semi-sync + innodb_flush_log_at_trx_commit=1 + sync_binlog=1 조합 필요.

Outbox Pattern (cross-DB consistency)

Multi-DB transaction 불가능 → outbox 로 eventual consistency.

-- ledgerdb 의 한 transaction 안에서
START TRANSACTION;
  -- 1. business operation
  INSERT INTO ledger_entries (...) VALUES (...);

  -- 2. outbox row (같은 DB transaction)
  INSERT INTO outbox (id, target_db, target_aggregate, payload_cbor, created_at, ...)
  VALUES (UUID_TO_BIN(UUID(), 1), 'auditdb', 'audit_events', ?, NOW(6), ...);
COMMIT;

-- 별도 worker:
-- outbox row 를 target DB 로 idempotent replicate
-- INSERT ... ON DUPLICATE KEY UPDATE id=id  (no-op merge)

Idempotency SQL Pattern

-- 1. INSERT IGNORE 로 중복 시 무시 (reference_id 는 UNIQUE)
INSERT IGNORE INTO withdrawals (id, reference_id, ...)
VALUES (UUID_TO_BIN(UUID(), 1), ?, ...);

-- 2. 항상 같은 row 를 반환 (신규 / 기존 무관)
SELECT id FROM withdrawals WHERE reference_id = ? LIMIT 1;

-- 단일 transaction 안에서 두 쿼리 모두 실행하면
-- "first writer wins, 이후는 동일 row 반환" 보장 (reference_id UNIQUE 전제).

UUID 저장 권장

  • UUID_TO_BIN(UUID(), 1) — 16-byte BINARY, time-ordered swap
  • String UUID 보다 50% 작고, B-tree index locality 향상

MySQL 에 없는 PostgreSQL 기능 → Alternative

PostgreSQLMySQL alternative
RETURNING별도 SELECT 또는 LAST_INSERT_ID() (AUTO_INCREMENT 전용)
ON CONFLICT ... DO NOTHINGINSERT IGNORE
ON CONFLICT ... DO UPDATEINSERT ... ON DUPLICATE KEY UPDATE
gen_random_uuid()UUID() 또는 UUID_TO_BIN(UUID(), 1)
jsonbJSON (MySQL 5.7+). Partial-index 는 generated column 필요
Partial indexGenerated column + index
Array typeJSON 또는 normalized child table
SAVEPOINT scopingMySQL 도 지원하나 deadlock detection 다름

Partitioning / Retention

테이블PartitionRetention
customers / vault_accounts / users / addressesN/A (cardinality 낮음)infinite
ledger_entriesper-month RANGE (가장 빠른 growth)regulatory retention (7-10y)
transactions / broadcast_attempts / confirmationsper-month RANGE7y
chain_eventsper-month RANGE + per-chain LIST (composite)5y
approval_requests / approval_decisionsper-month RANGE7y
signing_events / key_lifecycleper-month RANGEinfinite (audit critical)
audit_eventsper-tenant LIST (또는 per-month) — scale 의존infinite
withdrawalsper-month RANGE7y
recovery_eventsper-year RANGE (volume 낮음)infinite
health_checksper-day RANGE — partition drop 으로 archival90d

Schema Migration 의 Governance

ChangeGovernance
M-mut 컬럼 추가 / 변경일반 review
A-set 컬럼 추가일반 review
새 trigger 추가 (append-only enforcement)governance event
기존 trigger 변경 (특히 append-only)charter-class
Forbidden column 의식적 추가금지
새 테이블 추가일반 review
테이블 drop절대 금지 (soft archive 만)

Audit-Reviewable Schema 의 7 기준

  1. 모든 mutable 컬럼은 audit trail 동반
  2. 모든 append-only 테이블은 DB-level enforcement (trigger)
  3. Hash chain integrity 가 외부 검증 가능 (SGX/DCAP + signed checkpoint)
  4. Cross-DB binding 이 evidence chain 으로 입증
  5. Set-once 컬럼이 명시됨
  6. Runtime-only / forbidden 영역의 schema 부재가 검증됨
  7. State machine sticky terminal 이 DB-level 강제