對幻讀的思考

2022-06-19 06:33:12 字數 1536 閱讀 9684

參考自極客時間-mysql實戰45講

幻讀指的是乙個事務在前後兩次查詢同乙個範圍的時候,後一次查詢看到了前一次查詢沒有看到的行。

幻讀僅發生在「當前讀」的情況下。

請思考一下,為什麼只有在當前讀下會發生?

如果是快照讀,在該事務之後的其他事務的變更,當前事務一定看不到,不可能發生幻讀。

問題

表結構

create table `t` (

`id` int not null,

`c` int default null,

`d` int default null,

primary key (`id`),

key `c` (`c`)

) engine=innodb default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;

初始資料

t3時刻情況下,session a是算發生了幻讀嗎?

不算,session a為修改了舊行而查詢到了資料。只有「新插入的行」才算幻讀。

語義上的問題select ... for update;的語義是鎖住所有符合條件的記錄,不允許進行讀寫操作(即加了寫鎖)。而幻讀會使得插入新的符合條件的記錄,明顯破壞了該條sql語義。

資料一致性問題:會導致binlog寫入日誌的順序問題,導致備份庫/從庫的資料不一致問題。

間隙鎖。保證了行與行之間拒絕插入了新的記錄。

間隙鎖和行鎖合稱next-key lock,每個next-key lock是前開後閉區間。

間隙鎖的問題:因為不同間隙鎖之間並不互斥,可能導致不同session的相互等待導致死鎖,使得併發度降低,鎖住更大的範圍。

那麼如何取消使用間隙鎖?

間隙鎖只會在可重複讀級別下生效,所以把隔離級別調整為讀提交即可。(其實讀提交也是會發生幻讀,但是好像認為這算feature,在可重複讀情況下這算bug???)

但是需要解決資料和日誌可能不一致的問題,需要將binlog_format=row

binary logging formats :binlog的格式有statement、row、mixed。

statement:記錄執行的sql。

row:記錄每一條記錄被修改就結果。

mixed:ddl使用statement、dml使用row。

mysql幻讀 mysql 幻讀

幻讀 phantom read 是指當使用者讀取某一範圍的資料行時,b事務在該範圍內插入了新行,當使用者再讀取該範圍的資料行時,會發現有新的 幻影 行。innodb和falcon儲存引擎通 過多版本併發控制機制解決了幻讀問題。a事務讀取了b事務已經提交的新增資料,此時 a 還沒有提交,當前提交後,也...

讀髒資料,不可重複讀,幻讀的思考

1前提 事務併發 2.髒讀 a讀取資料d,修改資料d,b讀取d,a回滾。解決 a讀之前加乙個寫鎖,直到事務結束才釋放,各事務讀之前加讀鎖,防止被修改,對應資料庫隔離等級2 預設等級 3.不可重複讀 因為讀鎖獲取後,並不會持續到事務結束才釋放,有可能中途有別的事務獲取寫鎖,從而導致事務2次讀取同乙個資...

幻讀以及幻讀的解決方案

事務a 事務b事務a按照特定的條件查詢資料,查詢到了2條資料 事務b插入一條資料 commit 事務a按照原條件查詢資料,查詢到還是2條資料 事務a修改其中一條資料的值update,看到修改的範圍是3條資料 事務a按照原條件查詢資料,查詢到3條資料 為什麼出現幻讀 主要原因是快照讀和當前讀混合使用 ...