MySQL 在當(dāng)前讀的情況下,如果看到了其他事務(wù)新插入的一條數(shù)據(jù)构挤,這種情況稱為幻讀髓介。
是指一個事務(wù)在前后兩次查詢同一個范圍的時候,后一次查詢看到了前一次查詢沒有看到的行筋现。
- 在 可重復(fù)讀 的隔離級別下唐础,普通的查詢時快照讀,是不會看到別的事務(wù)插入的數(shù)據(jù)的矾飞。因此一膨,幻讀在“當(dāng)前讀” 下才會出現(xiàn)。
- 幻讀僅指新插入的行洒沦。
幻讀的影響
語義上的影響豹绪。例如下圖:
sessionA 聲明了“我要把所有 d=5 的行鎖住,不準(zhǔn)別的事務(wù)進(jìn)行再進(jìn)行操作”申眼。而實際上瞒津,這個語義被破壞了。
數(shù)據(jù)一致性的問題括尸。鎖的設(shè)計師為了保證數(shù)據(jù)的一致性巷蚪,一致性不只是數(shù)據(jù)庫內(nèi)部數(shù)據(jù)狀態(tài)的一致性,還包含了數(shù)據(jù)和日志在邏輯上的一致性濒翻。
如果出現(xiàn)幻讀屁柏,數(shù)據(jù)庫的binlog 的順序就會錯亂啦膜,因為 binlog 是在事務(wù)提交之后記錄的。如果使用了這樣的binlog 去備庫執(zhí)行或是克隆一個庫前联,就會出問題。
如何解決幻讀
為了解決幻讀娶眷,InnoDB 引入了新的鎖似嗤,就是間隙鎖(gap lock)。
間隙鎖就是在執(zhí)行當(dāng)前讀的時候届宠,不止是給數(shù)據(jù)庫已有的數(shù)據(jù)加上行鎖烁落,還同時加了間隙鎖,確保無法插入新的記錄豌注。
間隙鎖只跟“往這個間隙中插入一條記錄”這個操作沖突伤塌。間隙鎖之間不存在沖突。
間隙鎖與行鎖并稱為 next-key lock轧铁。
但是間隙鎖的引入每聪,可能會導(dǎo)致同樣的語句鎖住了更大的范圍,這其實是影響了并發(fā)度的齿风。如果兩個事務(wù)同時插入一條數(shù)據(jù)药薯,而且持有同樣的間隙鎖,就會產(chǎn)生死鎖救斑。
有的公司會使用讀提交的隔離級別童本,然后把 binlog 的格式設(shè)置為 row,也可以解決間隙鎖會產(chǎn)生死鎖的問題脸候。但是具體的業(yè)務(wù)也需要具體分析穷娱。