mysql鎖之三種行級鎖介紹
本文主要介紹
1.mysql三種行鎖介紹
2.RR模式下,next-key lock為什麼可以解決幻讀問題
首先,建立一張表:
mysql> show create table test01\G
*************************** 1. row ***************************
Table: test01
Create Table: CREATE TABLE `test01` (
`c1` bigint(20) NOT NULL AUTO_INCREMENT,
`c2` int(11) DEFAULT NULL,
`c3` varchar(20) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
初始化資料:
mysql> select * from test01;
+----+------+------+
| c1 | c2 | c3 |
+----+------+------+
| 1 | 1 | a |
| 2 | 2 | b |
| 3 | 3 | c |
| 4 | 4 | d |
| 5 | 5 | e |
+----+------+------+
5 rows in set (0.00 sec)
record lock:
在資料行本身加的鎖。
會話A
mysql> begin ;
Query OK, 0 rows affected (0.00 sec)
mysql> select c1 from test01 where c1=1 for update;
+----+
| c1 |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
會話B
mysql> update test01 set c1=6 where c1=1; --hang
c1=1上有record lock,所以會話B無法修改。
mysql> SHOW ENGINE INNODB STATUS\G
------- TRX HAS BEEN WAITING 4 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 24 page no 3 n bits 72 index PRIMARY of table `ming`.`test01` trx id 1807 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 6; hex 000000000708; asc ;;
2: len 7; hex a80000011c0110; asc ;;
3: len 4; hex 80000001; asc ;;
4: len 1; hex 61; asc a;;
gap lock:
在gap上加的鎖,不包括記錄本身。
需要建立一個非唯一性的索引,不能是主鍵或者唯一性索引,否則只有record lock。
mysql> create index idx_test01_c2 on test01(c2);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
初始化資料:
mysql> select * from test01;
+----+------+------+
| c1 | c2 | c3 |
+----+------+------+
| 1 | 1 | a |
| 3 | 3 | c |
| 5 | 5 | e |
| 7 | 7 | e |
+----+------+------+
4 rows in set (0.00 sec)
會話A:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select c2 from test01 where c2>3 and c2<5 for update;
Empty set (0.00 sec)
會話B
mysql> insert into test01 select 4,4,'e'; --hang
(3,3)與(5,5)之間的gap被鎖住了,所以無法插入(4,4)。
------- TRX HAS BEEN WAITING 32 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 24 page no 4 n bits 72 index idx_test01_c2 of table `ming`.`test01` trx id 1925 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 80000005; asc ;;
1: len 8; hex 8000000000000005; asc ;;
此時c2=3和c2=5兩行資料是可以更改的,但是改變後的值不能在現在的gap中。關於資料行的gap具體的可以參考下面的例子:、
next-key lock
對資料記錄本身和gap都加鎖,相當於record lock + gap lock。
c3列無用,刪除
mysql> alter table test01 drop column c3;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
初始化資料:
mysql> select * from test01;
+----+------+
| c1 | c2 |
+----+------+
| 2 | 2 |
| 5 | 5 |
| 7 | 7 |
+----+------+
3 rows in set (0.00 sec)
會話A:
mysql> begin ;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test01 where c2=5 for update;
+----+------+
| c1 | c2 |
+----+------+
| 5 | 5 |
+----+------+
1 row in set (0.00 sec)
會話B:
insert into test01 select 1,2; --ok
insert into test01 select 3,2; --hang
insert into test01 select 4,5; --hang
insert into test01 select 6,5; --hang
insert into test01 select 8,7; --ok
update test01 set c2=3 where c2=2; --hang
update test01 set c2=1 where c2=2; --ok
update test01 set c2=6 where c2=7; --hang
update test01 set c2=8 where c2=7; --ok
會話A在c2=5及gap上加了next-key lock,在資料行本身加了record lock,在c2=5資料行與其相鄰的上下兩行資料(c2=2,c2=7)之間的gap加了gap lock。
注意到(1,2)可以插入,但是(3,2)卻無法插入,有人或許會有疑問,c2都是2,為什麼一個可以插入一個不能插入?注意,next-key lock是在索引上加鎖,索引是有順序的,如下:
(1,2)--> (2,2) --> (5,5)
|-gap-|
注意到(1,2)在gap之外,所以是可以插入的。假設(3,2)可以插入,那麼它們在索引中的順序將是
(2,2) --> (3,2) --> (5,5)
|----gap----|
(3,2)將會插入到gap中,所以(3,2)是無法插入的。
會話B其它的sql也是這個道理。
經常看到一個說法是,next-key lock解決了RR隔離級別下的幻讀問題,那麼是如何做到的呢?
什麼叫幻讀?
一個事務裡面,多次查詢出的結果集不一致,這種情況就叫做幻讀。
下面是幻讀現象的一個例子:
會話A
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test01;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
| 5 | 5 |
| 7 | 7 |
+----+------+
3 rows in set (0.00 sec)
會話B
mysql> insert into test01 select 8,8 ;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
會話A
mysql> select * from test01;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
| 5 | 5 |
| 7 | 7 |
+----+------+
3 rows in set (0.00 sec)
mysql> insert into test01 select 8,8 ;
ERROR 1062 (23000): Duplicate entry '8' for key 'PRIMARY'
會話A明明沒有讀到c1=8的記錄,但就是無法插入,這就出現了幻讀現象。
如果會話A在開始事務後,
select * from test01 for update;
或者
select * from test01 lock in share mode;
那麼會話B根本無法對資料做任何修改,那麼這也就解決了幻讀問題。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31480688/viewspace-2650414/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等Java
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等...Java
- MySQL樂觀鎖和悲觀鎖介紹MySql
- MySQL 行級鎖之 間隙鎖、臨鍵鎖MySql
- MySQL資料庫鎖介紹MySql資料庫
- 你真的會用mysql行級鎖嗎?mysql 行級鎖全解析MySql
- MySQL鎖之三:MySQL的共享鎖與排它鎖編碼演示MySql
- Java中15種鎖的介紹Java
- MySQL複習筆記(05):MySQL表級鎖和行級鎖MySql筆記
- 【MySQL】死鎖案例之三MySql
- MySQL行級鎖測試MySql
- Mysql鎖之行級鎖和表級意向鎖MySql
- Java 中15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖,樂觀鎖,分段鎖,自旋鎖等等Java
- ORACLE鎖介紹Oracle
- MySQL內部實現讀鎖和寫鎖的具體鎖定型別介紹MySql型別
- 【Java面試】為什麼引入偏向鎖、輕量級鎖,介紹下升級流程Java面試
- mysql 行級鎖(按照粒度分類)MySql
- MySQL 避免行鎖升級為表鎖——使用高效的索引MySql索引
- MySQL 行級鎖的使用以及死鎖的預防MySql
- MySQL全域性鎖、表鎖以及行鎖MySql
- 詳解 MySql InnoDB 中的三種行鎖(記錄鎖、間隙鎖與臨鍵鎖)MySql
- MySQL -- 行鎖MySql
- MySQL 行鎖MySql
- Oracle的TX鎖(行級鎖、事務鎖)Oracle
- 簡單介紹redis加鎖常用幾種方式Redis
- MongoDB資料庫級別的鎖粒度介紹MongoDB資料庫
- MySQL 當中的各種鎖(中級篇)MySql
- MySQL鎖:03.InnoDB行鎖MySql
- Mysql在InnoDB引擎下索引失效行級鎖變表鎖案例MySql索引
- 資料庫系列:MySQL InnoDB鎖機制介紹資料庫MySql
- Oracle鎖簡單介紹Oracle
- ORACLE 鎖簡單介紹Oracle
- 執行緒和鎖,鎖升級執行緒
- MySQL 行級鎖的特點、分類MySql
- 廣義多執行緒安全之鎖與iOS鎖簡單介紹執行緒iOS
- mysql行鎖和死鎖檢測MySql
- MySQL索引失效行鎖變表鎖MySql索引
- 簡單介紹MySQL列印死鎖日誌的方法MySql