交易隔離等級
wordsCount: 1245
readingTime: 3 mins
viewers:
What we talk this ?
在不同的商業模式下,注重的核心不同,有些要速度,可接受不準確,有些要資料精準,可接受慢一點,有些則絕對不能錯, 所以可透過隔離等級調整資料庫行為,並加上sql語法的調整來做到目標
Isolation Level 交易隔離等級
併發性能&資料一致性成反比
| 隔離級別 | Dirty Read | Non-Rep. Read | Phantom Read | Write Skew | 實作機制 / 特性 | 適用情境 | |
|---|---|---|---|---|---|---|---|
| Read Uncommitted | ✅ 可能 | ✅ 可能 | ✅ 可能 | ❌ 可能 | 幾乎不加鎖,直接讀取記憶體中的變動 | 極端效能需求 (極少用) | |
| Read Committed | ❌ 不會 | ✅ 可能 | ✅ 可能 | ❌ 可能 | 每次Statement執行時取得新快照 | PostgreSQL, SQL Server預設 | |
| Repeatable Read | ❌ 不會 | ❌ 不會 | PostgreSQL❌ ,MySQL❗可能 | ❗可能 | Transaction時固定快照 | MySQL 預設 | PostgreSQL (RR)與SQL Server (SI)透過快照機制已經完全解決幻讀。**MySQL (RR)**則是在快照讀下解決,但當前讀(如UPDATE)仍可能觸發幻讀。 |
| Serializable | ❌ 不會 | ❌ 不會 | ❌ 不會 | ❌不會 | SSI (感應式序列化) 或兩階段鎖定 (2PL) | 財務清算、嚴格一致性要求 | |
| Snapshot Isolation(非標準) | ❌ 不會 | ❌ 不會 | ❌不會 | ❗可能 | 以快照為準,PostgreSQL 的 RR 實質為此級別 | 高併發且需避免幻讀,但要注意寫入衝突 | |
| Linearizable(分散式) | ❌ 不會 | ❌ 不會 | ❌ 不會 | ❌不會 | 結合時鐘同步,保證「真實時間」的全域順序 | 分散式鎖 (etcd)、全域資料庫 (Spanner) |
1.Read Uncommitted (RU)
問題:髒讀 Dirty Read
還沒commit的東西,就可以讀到
適用:效能第一
| Transaction A | Transaction B |
|---|---|
BEGIN;SELECT money FROM customer WHERE id = 1;/* money = 100 */ |
|
BEGIN;UPDATE customer SET money = 2000 WHERE id = 1;/* money = 2000 */ |
|
SELECT money FROM customer WHERE id = 1;/* money = 2000 */ |
|
髒讀 (Dirty Read)/* money = 2000 *//* money 實際為 100,但 Transaction A 以為是 2000 */ |
ROLLBACK;/* money = 100 */ |
下個級別有改善: 交易要做commit才會被其他交易看到
2.Read Committed(RC) (Oracle,PostgreSQL,SQL Server預設)
問題:不可重複讀 Non-repeatable read
一個交易內可能兩次無法讀到一樣的東西
A交易時間較長,讀取後,B交易快速完成,導致A交易再次讀取會讀到不一樣的東西(資料的即時性)
適用:高流量
如果前面的檢查邏輯過了,後面再次查詢,邏輯上沒有連貫性
| Transaction A | Transaction B |
|---|---|
BEGIN;SELECT money FROM customer WHERE id = 1;/* money = 500 */ |
|
BEGIN;UPDATE customer SET money = 2000 WHERE id = 1;/* money = 2000 */ |
|
COMMIT;/* money = 2000 */ |
|
SELECT money FROM customer WHERE id = 1;/* money = 2000 */ |
|
| 無法重覆讀取到相同結果 (non-repeatable read)第一次讀到 money = 500第二次讀到 money = 2000 |
下個級別改善: 讀取過的列,其他交易來做變更,我一樣還會讀到同樣的資料
3.Repeatable Read(RR) (MySQL的預設)
問題:幻讀 Phantom Read
因為交易做快照,來保證看到同樣的東西(MVCC),但實際上是有變更,資料庫內有多版本
| Transaction A | Transaction B |
|---|---|
BEGIN;SELECT * FROM product ;/* id=1 , price= 300 */ |
|
BEGIN;INSERT INTO product VALUES (2, 500);COMMIT; |
|
SELECT * FROM product ;/* id=1 , price= 300 *//* id=2 , price= 500 */ |
|
| 幻讀 (Phantom Read)兩次取得的筆數不相同 |
Phantom Read (幻讀):
- **PostgreSQL RR**:採用 Snapshot Isolation。事務開始那一刻,整個資料庫的狀態就固定了,**絕對讀不到**後來插入的行。所以 PG 的 RR 是**不會**有幻讀的。
- **MySQL RR**:雖然有 Gap Lock,但它是為了保護「寫入」和「強致讀取」。如果你只用普通的`SELECT`(快照讀),雖然不會看到新行,但如果你接著執行`UPDATE`或`INSERT`碰到新行,就會產生衝突或讓新行現身。因此 MySQL 的 RR**並未百分之百**解決幻讀。
4.Serializable 序列化:
交易期間,不給讀取,高流量災難
適用:精准度第一
Table of Contents
Related Posts
設計模式-工廠模式
Factory -工廠模式 分類 建立模式-Creational Patterns 主要角色 Product (產品介面)、Concrete Product (具體產品
2026-4-12
設計模式-策略模式
Strategy-策略模式 分類 行為模式-Behavioral Patterns 主要角色 Strategy (策略介面)、Concret
2026-4-12
MySQL和PostgreSQL交易快照比較
此篇討論Mysql和PostgreSQL的快照機制 MVCC (Multi-Version Concurrency Control) 多版本併發控制,核心在於使用版本來代替鎖來
2026-4-12
Mysql 的 Repeatable Read & 幻讀
此篇討論Mysql RR下,預設解決了哪些幻讀,哪些沒解決?如何處理剩下的幻讀問題 定義 快照讀 : select 當前讀
2026-4-12
交易併發問題
What we talk this ? 介紹基本定義,沒搞清楚就不知道交易隔離等級解決了什麼問題 交易併發常見問題 定義: 問題類型 定義
2026-4-12
Sponsor
Wechat
Alipay