MySQL InnoDB 事務隔離級別如何實現
阿新 • • 發佈:2020-08-18
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
未提交讀(Read uncommitted) | 可能 | 可能 | 可能 |
已提交讀(Read committed) | 不可能 | 可能 | 可能 |
可重複讀(Repeatable read) | 不可能 | 不可能 | 可能 |
可序列化(Serializable) | 不可能 | 不可能 | 不可能 |
- 未提交讀(Read Uncommitted):允許髒讀,也就是可能讀取到其他會話中未提交事務修改的資料
- 已提交讀(Read Committed):只能讀取到已經提交的資料。Oracle等多數資料庫預設都是該級別 (不重複讀)
- 可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB預設級別。在SQL標準中,該隔離級別消除了不可重複讀,但是還存在幻象讀
- 可序列化(Serializable):完全序列化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞
InnoDB預設是行級鎖,內部會生成三個隱藏欄位:db_trx_id
(事務id)、db_roll_pt
(回滾指標)、delete_flag
(刪除標記)
版本鏈使用場景(readView)
- 當前操作的事務id為102,假設版本鏈資料[1,2,100,101],活躍列表為[100,101],活躍列表就是未提交的活躍事務,因此事務2是已提交,所以事務5會拷貝一份事務2並插入版本鏈最後一個元素
- 當隔離界別為
可重複讀
,需要操作事務查詢或修改時,那麼就單獨讀取事務102的資料,這樣就能實現隔離其他未提交的事務。 - 當隔離界別為
讀已提交
DML操作
- INSERT:建立一條資料,
db_trx_id
的值為當前事務 id,db_roll_pt
為 null 。 - UPDATE:複製一行資料,將當前複製後這一行的
db_trx_id
置為當前事務的 id,db_roll_pt
是一個指標,指向複製前的那一條的。 - DELETE:複製一行資料,將當前複製後這一行的
db_trx_id
置為當前事務的 id,db_roll_pt
是一個指標,指向複製前的那一條的。並把delete_flag
置為 true 。