Engineering · 1 min read
mutex 只提供 ACID 的隔離性,其餘全靠自己
把 login() 包進一把鎖,看似像資料庫交易一樣安全,其實 mutex 只提供 ACID 四項特性中的隔離性,原子性與持久性都必須自己手動處理。
mutex 只提供 ACID 的「I」,沒有 A、C、D
把 login() 包進一把鎖,看似就像包進一個資料庫交易一樣安全,但其實鎖只提供了 ACID 四個字母裡的一個:I(Isolation,隔離性)。
鎖和 DB 交易都會把並發工作序列化,但兩者提供的保證差很多:
| ACID | DB 交易 | mutex |
|---|---|---|
| Atomicity(回滾) | 有 | 沒有——臨界區中途拋錯會留半成品 |
| Consistency(不變量) | 引擎強制 | 程式碼自行維護 |
| Isolation(隔離) | 有(可調) | 有——類似 Serializable |
| Durability(持久) | 落盤 | 沒有(純記憶體) |
除了這張表,還有兩個結構性差異值得記住:
- 交易保護的是資料(引擎對所有存取者強制);mutex 保護的是程式碼路徑(只有自願取同一把鎖的執行緒才受保護)。
- 它是「必須結束才換下一個」,不是「必須成功」。失敗的交易會回滾;失敗的臨界區可能留下爛攤子給下一位持鎖者。
也正因如此,login() 才需要手動避免回滾問題(先做完再發佈)——鎖不會自動還原半完成的寫入。
鎖序列化的是「執行」,不是「成功」。想要原子性,得自己動手。
參考來源:
- http://ithare.com/databases-101-acid-mvcc-vs-locks-transaction-isolation-levels-and-concurrency/
- https://www.designgurus.io/blog/acid-database-transaction
Related: 參見先做完再發佈的安全發佈模式,或回到讓 login 執行緒安全的四筆學費總覽。