mysql 鎖 事務隔離級別

主題

最近在看mysql相關的書籍.實驗了一些內容.分享一下,主要是關於事務隔離級別(read-committed和repeatable-read)和鎖相關的.mysql

 

不少網上文章上都能搜索到 read-committed能夠防止髒數據.可是不能防止 不可重複讀.sql

而repeatable-read能夠防止 不可重複讀.可是不能防止幻讀.session

如今我想分享下具體是怎麼操做的. 日誌

 

不可重複讀下的區別

read-committed和repeatable-read的區別究竟是什麼?索引

我以爲在 不可重複讀 這個問題上並無涉及鎖的問題.而是涉及一致性非鎖定讀的問題事務

 

假設有一張user,主鍵id int, name varchar, i varchar.it

在i這一列上有索引,非惟一.io

數據以下:table

id  name  idate

1  v1    i1

5  v5    i5

9  v9    i9

全部session的 autocommit=0 不會自動提交.

 

session A:

update user set name = 'v5-new' where id = 5;  

這個時候鎖定了id=5這一列.沒有commit

 

Session B:

select name from user where id = 5

查詢出來是v5.這是由於RR和RC都不會讀到髒數據

 

而後session A:

commited;

這個時候行最新的name已是v5-new了

 

Session B:

select name from user where id = 5

這個時候的select就有區別了.

RC讀出來是v5-new, RR仍然是v5

可是要注意的是Session B在這裏始終都只是通常的select,因此沒有加鎖.因此這裏不可重複和鎖我以爲沒有關係(可是和session A在記錄上加的X鎖有點關係,由於這條記錄被鎖定了).

那爲何2種隔離級別會有區別呢? 由於一致性非鎖定讀的緣由

 

session B第一次讀取發現記錄ID=5被鎖定(有X鎖).那讀的時候就會從undo日誌裏找到原始的值.也就是v5.

第二次讀的時候RC和RR有區別.RC由於session A已經committed,會讀最新的行數據,也就是v5-new

而RR仍然會讀取以前讀到的那個snap-shot版本,也就是v5.因此會有區別..

 

幻讀

RR模式下加上鎖能夠解決幻讀的問題(還原以前的數據).

實驗以下:

Session A:

update user set name = 'v55' where i = 'i5';

沒有committed

 

Session B:

insert into user values(6, 'v6', 'i5');

 

這個時候若是B能夠committed,那就會產生幻讀的問題.由於A明明修改了全部i=i5的數據.

可是卻沒有修改B插入的那條.

 

可是實際上Session B執行這個insert的時候回等待.

由於A鎖住了i = i5的數據.因此B是插入不了的.

 

那若是B執行的是

 insert into user values(6, 'v6', 'i6'); 能夠嗎?

事實上也會等待.由於A會鎖定i=i5的數據和它到上下兩條相鄰數據的區間.

也就是說 i1-i5, i5, i5-i9的數據都被鎖住了.都是不能插入的.

 insert into user values(10, 'v10', 'ia');

這條記錄就能夠插入.由於ia在i9以後(字母大於數字).

 

mysql對主鍵會鎖單條記錄.可是對非惟一的通常的索引,會鎖單條記錄加上上下範圍 

相關文章
相關標籤/搜索