事物的四個隔離狀態和幻讀

2021-10-24 14:17:41 字數 1272 閱讀 9815

讀未提交 read-uncommitted | 0:存在髒讀,不可重複讀,幻讀的問題

讀已提交 read-committed | 1:解決髒讀的問題,存在不可重複讀,幻讀的問題

可重複讀 repeatable-read | 2:解決髒讀,解決不可重複讀的問題(使用 mmvc機制實現可重複讀),但是存在幻讀的問題,預設隔離級別。

序列化 serializable | 3:解決髒讀,解決不可重複讀,幻讀,可保證事務安全,但完全序列執行,效能最低

重點說一下幻讀

幻讀錯誤的理解:說幻讀是 事務a 執行兩次 select 操作得到不同的資料集,即 select 1 得到 10 條記錄,select 2 得到 11 條記錄。這其實並不是幻讀,這是不可重複讀的一種,只會在 ru 、rc 級別下出現,而 rr 隔離級別下僅通過mvcc機制就可以避免這種現象。

這裡給出我對幻讀的比較白話的理解:幻讀,並不是說兩次讀取獲取的結果集不同,幻讀側重的方面是某一次的 select 操作得到的結果所表徵的資料狀態無法支撐後續的業務操作。更為具體一些:select 某記錄是否存在,不存在,準備插入此記錄,但執行 insert 時發現此記錄已存在,無法插入,此時就發生了幻讀。

幻讀舉例:

table users: id primary key

step1 t1: begin;select * fromuserswhereid= 1; --t1查詢無記錄

step2 t2: begin;insert intousersvalues (1, 『big cat』); --t2插入id=1的記錄但是不提交

step3 t1: insert intousersvalues (1, 『big cat』); --t1插入id=1的記錄發現主鍵衝突

step4 t1: select * fromuserswhereid= 1; --t1再次查詢依然無記錄

結論:t1查不到id=1的記錄,但是插入一行id=1的記錄卻報主鍵衝突,這就是幻讀。

其實 rr 也是可以避免幻讀的,通過對 select 操作手動加 行x鎖(select … for update 這也正是 serializable 隔離級別下會隱式為你做的事情),同時還需要知道,即便當前記錄不存在,比如 id = 1 是不存在的,當前事務也會獲得一把記錄鎖(因為innodb的行鎖鎖定的是索引,故記錄實體存在與否沒關係,存在就加 行x鎖,不存在就加 next-key lock間隙x鎖),其他事務則無法插入此索引的記錄,故杜絕了幻讀。

事物的四個特性和四個隔離級別

事物是一條或者多條sql語句組成的執行序列,這個序列中的所有語句都屬於同乙個工作單元,要麼同時完成,其中如果有乙個失敗,則其他操作都要回滾。事物是乙個不可分割的資料庫邏輯工作單位,要麼全部完成,要不失敗回滾。事務執行的結果必須使資料庫從乙個一致性狀態變到另乙個一致性狀態。乙個事物的執行不能被別的併發...

事物隔離的四個級別

隔離級別 內容特點 read uncommited 讀未提交 向資料庫中插入了乙個值,此時並沒有提交,但是資料庫中已經看到這個值 例如 向資料庫update值 101,此時發現提交錯誤,查詢時發現值已經變成101,事物回滾後重新插入100 並提交,此時再查資料庫值已經變成100,讀未提交容易觸發髒讀...

事物的四個特性和隔離級別

一 什麼是事務 事務是應用程式中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,乙個事務中的一系列的操作要麼全部成功,要麼乙個都不做。事務的結束有兩種,當事務中的所以步驟全部成功執行時,事務提交。如果其中乙個步驟失敗,將發生回滾操作,撤消撤消之...