Mysql如何解決幻讀

2021-10-01 23:19:00 字數 1799 閱讀 3792

日常開發中接觸到最多的事務隔離級別分別是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...