丟失更新
示例:
| Time | T1 | T2 |
|---|---|---|
| t1 | start | start |
| t2 | SELECT m=100 | SELECT m=100 |
| t3 | UPDATE m-=10 | |
| t4 | UPDATE m+=20 | commit |
| t5 | commit | |
| t6 | (此時m=120) | (t3處的更新丟失) |
兩個事務都對同一條記錄的值進行了查詢和更新操作,并先后提交,其中先提交的事務(T2)中的更新操作結(jié)果會被后提交的事務(T1)的更新操作結(jié)果覆蓋。先提交的事務(T2)丟失更新。
臟讀
示例:
| Time | T1 | T2 |
|---|---|---|
| t1 | start | start |
| t2 | SELECT m=100 | |
| t3 | UPDATE m+=10 | |
| t4 | SELECT m=110 | rollback |
| t5 | 使用了110這個臟數(shù)據(jù)做某些操作或計算 | (此時m=100) |
一個事務(T1)內(nèi),讀取到了一個記錄的值并參與之后的計算。這個值是其它事務(T2)中更新后還未提交的,如果其它事務(T2)最終回滾,那么這個事務(T1)中讀取并參與計算的值就成了臟數(shù)據(jù)。把事務(T1)的這次讀取稱為臟讀。
不可重復讀
| Time | T1 | T2 |
|---|---|---|
| t1 | start | start |
| t2 | SELECT m=100 | SELECT m=100 |
| t3 | UPDATE m+=10 | |
| t4 | commit | |
| t4 | SELECT m=110 | |
| t5 | (先后兩次讀取的值不一致) | (此時m=110) |
一個事務內(nèi),對同一條記錄進行了前后兩次查詢,在這兩次查詢之間其它事務對該記錄的值做了更新并提交操作,導致這兩次查詢的結(jié)果不一致。事務(T1)第一次的讀取不可再之后重復。
幻讀
| Time | T1 | T2 |
|---|---|---|
| t1 | start | start |
| t2 | SELECT id=12的記錄(不存在) | |
| t3 | INSERT id=12的記錄 | |
| t4 | commit | |
| t5 | INSERT id=12的記錄(主鍵沖突) | |
| t6 | (id=12的記錄的存在狀態(tài)不一致) | (此時id=12的記錄存在) |
一個事務內(nèi),由于其它事務(T2)的對一條記錄的插入或刪除操作導致當前事務(T2)得到這條記錄的存在狀態(tài)不一致。
MySQL的事務隔離級別
| 隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
|---|---|---|---|
| Read uncommitted | 可能 | 可能 | 可能 |
| Read committed | 不可能 | 可能 | 可能 |
| Repeatable read | 不可能 | 不可能 | 可能 |
| Serializable | 不可能 | 不可能 | 不可能 |
--- EOF ---