MySQL選用可重複讀之前一定要想到的事情(無索引加鎖驗證)
之前的實驗,提到過一個場景
當前讀(鎖定讀)加鎖情況.
但是如何驗證讀提交隔離級別,會鎖定所有主鍵主鍵,而在伺服器層解鎖呢?
http://blog.itpub.net/29254281/viewspace-1398273/
實驗資料如下:
create table t
(
a int primary key,
b int,
c int
) engine=innodb;
insert into t
values
(1,10,10),
(3,10,20),
(5,20,30),
(7,20,40),
(9,20,50);
commit;
首先,可重複讀隔離級別.
終端一:
select * from t where b=20 and c=30 for update;
終端二:
delete from t where b=20 and c=50;
阻塞
檢視鎖情況
select * from information_schema.innodb_locks;
可以看到鎖定的資料是主鍵索引 1
這是因為終端一已經鎖定了所有的主鍵索引和主鍵索引間隙.
終端二獲取第一個主鍵索引就被阻塞.
同樣的過程,改為讀提交隔離級別.
終端一
select * from t where b=20 and c=30 for update;
終端二
delete from t where b=20 and c=50;
阻塞
檢視鎖情況
select * from information_schema.innodb_locks;
可以看到鎖定了主鍵索引 5
這驗證了何老師的說法,
就是在讀提交隔離級別,對所有的主鍵索引上鎖,在伺服器層釋放不符合條件的鎖,
也就是說終端一鎖定了所有的主鍵索引,在伺服器層釋放了其他主鍵索引的鎖,只保留了a=5的鎖.
終端二開始加鎖,加到a=5的主鍵索引不能獲取,所以阻塞
從現象看,如果終端一的語句不走二級索引或者主鍵索引,終端二的語句都會阻塞,
但是不同的是,可重複讀鎖定所有主鍵索引和主鍵索引間隙,
而讀提交最終只會鎖定相關記錄的主鍵索引.
那麼在讀提交的隔離級別下,下面的語句不會阻塞
select * from t where a=1 for update;
而在可重複讀隔離級別下,上面的語句就會阻塞.
當前讀(鎖定讀)加鎖情況.
|
讀提交 | 可重複讀 |
主鍵索引 |
鎖定主鍵索引 |
鎖定主鍵索引 |
唯一索引 |
鎖定唯一索引的值和主鍵索引的值 |
鎖定唯一索引的值和主鍵索引的值 |
普通索引 |
鎖定普通索引的值和主鍵索引的值 |
鎖定普通索引的值和主鍵索引的值,普通索引增加間隙鎖 |
無索引 |
鎖定所有的主鍵索引,在伺服器層對不符合條件的記錄解鎖 |
鎖定所有的主鍵索引和主鍵索引的間隙 |
但是如何驗證讀提交隔離級別,會鎖定所有主鍵主鍵,而在伺服器層解鎖呢?
http://blog.itpub.net/29254281/viewspace-1398273/
實驗資料如下:
create table t
(
a int primary key,
b int,
c int
) engine=innodb;
insert into t
values
(1,10,10),
(3,10,20),
(5,20,30),
(7,20,40),
(9,20,50);
commit;
首先,可重複讀隔離級別.
終端一:
select * from t where b=20 and c=30 for update;
終端二:
delete from t where b=20 and c=50;
阻塞
檢視鎖情況
select * from information_schema.innodb_locks;
可以看到鎖定的資料是主鍵索引 1
這是因為終端一已經鎖定了所有的主鍵索引和主鍵索引間隙.
終端二獲取第一個主鍵索引就被阻塞.
同樣的過程,改為讀提交隔離級別.
終端一
select * from t where b=20 and c=30 for update;
終端二
delete from t where b=20 and c=50;
阻塞
檢視鎖情況
select * from information_schema.innodb_locks;
可以看到鎖定了主鍵索引 5
這驗證了何老師的說法,
就是在讀提交隔離級別,對所有的主鍵索引上鎖,在伺服器層釋放不符合條件的鎖,
也就是說終端一鎖定了所有的主鍵索引,在伺服器層釋放了其他主鍵索引的鎖,只保留了a=5的鎖.
終端二開始加鎖,加到a=5的主鍵索引不能獲取,所以阻塞
從現象看,如果終端一的語句不走二級索引或者主鍵索引,終端二的語句都會阻塞,
但是不同的是,可重複讀鎖定所有主鍵索引和主鍵索引間隙,
而讀提交最終只會鎖定相關記錄的主鍵索引.
那麼在讀提交的隔離級別下,下面的語句不會阻塞
select * from t where a=1 for update;
而在可重複讀隔離級別下,上面的語句就會阻塞.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1399645/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL選用可重複讀之前一定要想到的事情MySql
- MySQL選用可重複讀之前一定要想到的事情(ICP驗證和勘誤)MySql
- MySQL選用可重複讀之前一定要想到的事情(執行計劃影響)MySql
- MySQL在建立索引之前一定要想到的事情MySql索引
- MySQLDump在使用之前一定要想到的事情MySql
- 【MySQL】可重複讀下的幻讀MySql
- mysql加鎖讀MySql
- MySQL 之隔離級別:可重複讀MySql
- ZooKeeper 分散式鎖 Curator 原始碼 02:可重入鎖重複加鎖和鎖釋放分散式原始碼
- MySQL的可重複讀級別能解決幻讀嗎MySql
- Mysql可重複讀(1) —— 快照何時建立MySql
- Mysql RC/RR隔離原理和區別 不可重複讀和可重複讀MySql
- 為什麼mysql選可重複讀作為預設的隔離級別MySql
- 【MySQL】可重複讀模式下 unique key失效案例MySql模式
- 重讀 swift 之一:Optional(可選型)Swift
- MySQL 冗餘和重複索引薦MySql索引
- MySQL 實戰 | 08 懵逼,可重複讀好像失效了?MySql
- 驗證碼機制之驗證碼重複使用
- MySQL 可重複讀,差點就我背上了一個 P0 事故!MySql
- MySQL 事務隔離實驗-認識:髒讀、不可重複讀、幻讀MySql
- 簡單聊聊mysql的髒讀、不可重複讀MySql
- mysql之許可權驗證MySql
- MySQL5.5加主鍵鎖讀問題MySql
- MySql 中有 select … for update 來加讀鎖,那麼對應地在 DocumentDB中 如何加讀鎖MySql
- 故障案例:MySQL唯一索引有重複值,官方卻說This is not a bugMySql索引
- 用jquery驗證使用者名稱是否有效或重複jQuery
- InnoDB事務鎖之行鎖-聚集索引加鎖流程索引
- Mysql加鎖過程詳解(3)-關於mysql 幻讀理解MySql
- Mysql加鎖過程詳解(2)-關於mysql 幻讀理解MySql
- MySQL複合索引MySql索引
- golang原始碼分析:sync.Pool 如何從讀寫加鎖到無鎖Golang原始碼
- MySQL的可插入驗證和客戶端明文驗證外掛介紹MySql客戶端
- MySQL 8.0:無鎖可擴充套件的 WAL 設計MySql套件
- 優雅的實現請求類驗證規則的重複利用(無需繼承,可適用於多個請求類的規則合併)繼承
- MySQL鎖(四)行鎖的加鎖規則和案例MySql
- IPA加驅動的一種方式,未驗證
- 【Mysql】資料庫事務,髒讀、幻讀、不可重複讀MySql資料庫
- MySQL淺談(索引、鎖)MySql索引