日常開發中接觸到最多的事務隔離級別分別是read-committed和repeatable-read也就是我們常說的提交讀和可重複讀。innodb的rr級別和rc級別最大的區別就是增加了gap鎖也就是間隙鎖,那麼間隙鎖是如何解決幻讀的呢?
回憶一下幻讀和髒讀的概念,髒讀就是,乙個事物讀到了另乙個事務未提交的資料,這個很好理解,就是a事務修改一行資料但還沒有提交,b事務讀取了a修改的資料,然後a事務回滾,這時候b事務讀取到的就是髒資料。這時候注意一點就是解決髒讀的方式不管是mvcc還是普通的鎖都是針對資料庫中的記錄的,rc級別下可以解決髒讀問題,具體是如何解決的本文就不討論了,這時候設想一種場景:
先建個表:
create table `t_speak` (
`msg` varchar(255) default null,
`id` int(11) not null,
primary key (`id`)
) engine=innodb default charset=utf8;
假如a事務將表 t_speak 的一條記錄中的msg
修改為:「我想做個好人」,
start transaction;
update t_speak set msg = "我想做個好人" where id < 4;
我們知道id欄位在 沒有加索引的情況下,此時事務a會鎖住表t_speak的所有記錄,加了索引的情況下,會鎖住所有符合條件的索引。
這個時候b事務在表 t_speak插入一條資料msg
欄位為"去和法官說啊",id =0.
start transaction;
insert into `t_speak` (msg, id) values ("去和法官說啊", 0);
commit;
b事務在a事務前提交了,然後a事務查詢所有id <4的資料
select * from t_speak where id <4;
結果是這樣的:
奇怪的事情發生了,a事務還未提交,但是資料庫中就已經出現了不同的聲音,就像幻覺一樣,這就是幻讀!
為什麼會出現這種情況呢?剛剛說了事務a鎖住了表 t_speak所有符合條件的索引,此時事務a鎖住id=1,2的索引,它只鎖住了索引並沒有鎖著記錄的間隙,所以導致了其他事務可以插入一條id<4的記錄。
這個時候就需要將innodb的事務隔離級別修改為repeatable-read,因為rr級別不僅可以鎖住索引還可以鎖著索引的間隙。
事務a:
事務b:
事務b在等待事務a釋放鎖!
注意:在rr級別下事務a鎖住的不是id < 4的索引和間隙,而是id <=2的所有索引和間隙(表中沒有id=3的資料),因為事務id=4的索引並不是滿足條件的索引,也就是說事務b插入一條id = 3的記錄還是可以的,所以間隙鎖並沒有完全解決幻讀問題,感興趣的同學可以自己試試。
20200429 mysql 如何解決幻讀
前言 事務的隔離級別有四種,讀未提交,讀已提交,可重複讀和序列化,下面結合具體的問題,在mysql中,innodb引擎是怎麼解決幻讀的?什麼是幻讀?一次事務中,多次查詢,結果集的個數不一樣,就叫幻讀 多出來的行就叫做幻行 為什麼要解決幻讀 高併發資料庫,要保持資料庫的一致性 mysql解決幻讀的方式...
MySQL 是如何解決幻讀的
在一次事務裡面,多次查詢之後,結果集的個數不一致的情況叫做幻讀。而多或者少的那一行被叫做幻行 在高併發資料庫系統中,需要保證事務與事務之間的隔離性,還有事務本身的一致性。如果你看到了這篇文章,那麼我會預設你了解了髒讀 不可重複讀與可重複讀。多數資料庫都實現了多版本併發控制,並且都是靠儲存資料快照來實...
14 01 MySQL 幻讀如何解決?
如何解決幻讀問題?首先明確select 和 select for update 視為不相同的查詢,前者是 快照讀 而後者是 當前讀 假設有如下結構的表和資料 create tablet idint 11 not null,cint 11 default null,dint 11 default nu...