1. 程式人生 > 實用技巧 >MySQL InnoDB 事務隔離級別如何實現

MySQL InnoDB 事務隔離級別如何實現

隔離級別 髒讀 不可重複讀 幻讀
未提交讀(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)

  1. 當前操作的事務id為102,假設版本鏈資料[1,2,100,101],活躍列表為[100,101],活躍列表就是未提交的活躍事務,因此事務2是已提交,所以事務5會拷貝一份事務2並插入版本鏈最後一個元素
  2. 當隔離界別為可重複讀,需要操作事務查詢或修改時,那麼就單獨讀取事務102的資料,這樣就能實現隔離其他未提交的事務。
  3. 當隔離界別為讀已提交
    ,流程跟可重複讀差不多,但在每次讀取資料前都會生成一個readView,保證不會查詢到當前事務未提交的資料。

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 。