參考自極客時間-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條資料 為什麼出現幻讀 主要原因是快照讀和當前讀混合使用 ...