幻讀是什麼?幻讀有什麼問題
一:CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB;
insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);
begin;
select * from t where d=5 for update;
commit;
這條語句會命中d=5這一行,對應主鍵是id =5 ,這一行會加一個寫鎖。 由於d 上沒有索引,這條語句查詢的時候會做全表掃描。但是 不滿足條件的5行記錄上會不會加鎖呢?
二:幻讀是什麼:
查詢語句用的是當前讀,並且加上了些鎖。Q3讀到id = 1 這一行的現象稱為幻讀。
1.在可重複讀隔離級別下,普通查詢是快照讀,是不會看到別的事務插入的資料,幻讀在當前讀下才會出現。
2.sessionb 的修改結果被sessiona讀到,不能稱為幻讀,幻讀指的是行插入的行
幻讀有什麼問題:
1.語義上的。
sessonA是要給d=5的加鎖。但是sessionB ,sessionC 都可以執行成功。sessionA只是給id = 5 加了鎖。
2 。破壞了資料一致性
這個一致性,不止是資料庫內部資料狀態在此刻的一致性,還包含了資料和日誌在邏輯上的一致性。
update t set d=5 where id=0; /*(0,0,5)*/
update t set c=5 where id=0; /*(0,5,5)*/
insert into t values(1,1,5); /*(1,1,5)*/
update t set c=5 where id=1; /*(1,5,5)*/
update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/
insert into t values(1,1,5); /*(1,1,5)*/
update t set c=5 where id=1; /*(1,5,5)*/
update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/
update t set d=5 where id=0; /*(0,0,5)*/
update t set c=5 where id=0; /*(0,5,5)*/
上邊把表的所有資料都加了鎖,但是還是插入了資料 。
如何解決幻讀?
新插入的語句是更新的記錄之間的間隙。為了解決這個問題,引入了間隙鎖。
產生 了七個間隙 。
select * from t where d= 5 for update;,不止給6個記錄加上了行鎖。同時還加了7個間隙鎖。這樣就確保無法插入新的記錄。
跟間隙鎖存在衝突關係的是往這個間隙中插入一個記錄,這個操作。間隙鎖之間都不存在衝突關係。
這倆條語句都加了 (5,10)這個間隙鎖,但是不衝突,不會吧sessionB阻塞住。
select * from t for update 是把整個表的所有記錄鎖起來。就形成了7個next-key-lock.
但是也會出現問題。就是會發生死鎖;
可能會引出併發讀。