要点: Database ScaleはNode追加ではなく、時間と競合の場所を理解することから始まります。
課題
ApplicationはDB Connectionより速くScaleします。過大Pool、N+1、長TransactionがCapacityを枯渇させ、ReplicaはStale Readを、早すぎるShardingは複雑性を増やします。
単純な対策だけでは不十分な理由
CPU以外にもLock Wait、I/O、Buffer、Connection、Replicationが飽和します。
Deploy SurgeによるConnection StormをCapacity Planへ含めます。
処理フロー
有限Unit of Work→Pooler
Connection Budget→Primary
Writeと整合Read→Replica・Partition
計測済みOffload
アーキテクチャ上の判断
ConnectionをGlobal Budget化
MigrationとIncident用Reserveを残し、Hard Limitを配分します。
Use CaseごとのConsistency
BalanceやRead-after-writeはPrimary、許容時のみReplicaを使います。
Pruning目的のPartition
Scan削減やRetentionに効くKeyを選びます。
さらに深く考える
単独Latencyより総Work
短い高頻度QueryをFrequencyとRowsで評価します。
ShardingはOwnership設計
Shard Key、Cross-shard、Uniqueness、Rebalanceを事前設計します。
実装手順
- Global Connection BudgetをServiceとDeployへ配分します。
- 総Costの高いQueryを実Dataに近いPlanで改善します。
- ConsistencyとRoutingを決めてからReplicaやPartitionを追加します。
技術例: 有限TransactionとConsistency-aware Read
with db.transaction(timeout = 800ms) as tx:
order = tx.orders.lock(orderId)
tx.orders.update(orderId, nextState)
readTarget = PRIMARY if session.justWrote else REPLICA
return query(readTarget, tenantId, orderId)Network CallをTransaction外へ出し、外部TimeoutでLockを保持しないようにします。
想定すべき障害パターン
- Deploy SurgeがConnection上限を超えます。
- Replica Lagが購入直後に古い権限を返します。
- Index BuildがProduction Writeを飽和させます。
監視すべきシグナル
| シグナル | 確認する理由 |
|---|---|
| Active・Waiting Connection | 実処理とPool競合を分離します。 |
| Query Total Time・Rows | Fleet全体Costで優先します。 |
| Lock Wait・Replica Lag | 整合性とTail Latency Riskです。 |
設計の検証方法
- 最大ReplicaとDeploy Surgeを試験します。
- Replica LagでRead-after-writeを試験します。
- 実Volume相当でIndex Build影響を測ります。
安全なRollout計画
QueryとPoolを先に可視化し、Poolを段階縮小します。Stale許容経路一つへReplicaを追加し、Partition・ShardingはRollbackと照合を持つ別Programにします。
本番前チェックリスト
- 全TransactionにTimeoutと小さなScopeを持たせます。
- IndexはRead効果とWrite Costで評価します。
- Replica LagをApplication Routingへ反映します。
まとめ
Scale可能なDBは分割前にBudgetと予測可能なAccess Patternで守られます。
