BACKEND ADVANCED · 144
Database Concurrency:很多 Request 同時來時,資料規則還成立嗎?
單一 request 測試成功,不代表 production concurrency 正確。兩個 request 可能同時讀到舊值、同時寫入、搶 connection、造成 race。
Learning outcomes
- 能說明 connection pool 的角色。
- 能辨識 read-modify-write race。
- 能決定 transaction boundary。
- 知道 unique constraint 是 data-layer correctness tool。
1. Connection pool
HTTP requests
↓
Node process
↓
DB pool
├─ connection 1
├─ connection 2
└─ connection N
↓
Database每個 request 都新建 physical DB connection 通常成本過高;pool 重用有限連線資源。
2. Race condition
Request A:
read quota = 1
Request B:
read quota = 1
A inserts
B inserts
結果:超過 quota只在 service code 先查再 insert,並不能保證 concurrent correctness。
3. Transaction + constraint
需要依 DB 能力使用 transaction、locking、atomic update、unique/check constraints 等 mechanism,讓 correctness 在 data layer 也被 enforce。
4. Isolation 與 Constraint 是不同工具
Transaction 把一組操作包成一致性單位;isolation level 決定 concurrent transactions 彼此能看到什麼;constraint 則直接限制資料庫允許的最終 state。三者不能互相完全取代。
Application rule
↓
Transaction / atomic SQL
↓
UNIQUE / CHECK / FK
↓
Persistent invariant
如果 invariant 能由 database constraint 精確表達,通常值得在資料層再守一次,而不是只依賴某個 Node process 的 if。
5. Project checkpoint:Course creation quota
BEGIN
verify quota
insert course
insert audit record
COMMIT真正 implementation 取決於 DB isolation / schema;這裡先建立 boundary mental model。
Debug evidence
- 單元測試 pass,但壓測偶發 duplicate。
- DB unique violation。
- pool wait time 上升。
- transaction deadlock / timeout。
Knowledge check
- connection pool 解的是什麼資源問題?
- 為什麼「先 SELECT 再 INSERT」可能 race?
- application validation 與 DB constraint 為什麼常需要兩層?
- 替 Course API 設計一個原子 quota operation。