一个innod的表,如果根据没有索引的列去更新,那么很悲剧,会lock整个表。
update tmp_xf set c =11 where a = 1;
整个tmp_xf表都会被lock。
所以我们必须在列a上建索引,但是innodb的索引是会有间隙锁(Next-Key),主要是存在在update对insert的影响上,两个update之间没有影响。 看下面的测试
show create table tmp_xf\G
*************************** 1. row ***************************
Table: tmp_xf
Create Table: CREATE TABLE `tmp_xf` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT '10',
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=77 DEFAULT CHARSET=gbk;
select * from tmp_xf;
+----+------+------+------+------+
| id | a    | b    | c    | d    |
+----+------+------+------+------+
|  1 |    1 | NULL |   11 |   10 |
| 41 |   30 |    1 |    1 |   10 |
| 42 |   50 |    1 |    1 |   10 |
| 43 |  100 |    1 |    1 |   10 |
+----+------+------+------+------+
4 rows in set (0.00 sec)
session1:
update tmp_xf set c =11 where a = 1;
session2:
insert into tmp_xf (a,b,c) values (2,1,1);
Result:
a         lock range(all the row in the range can be inserted)
1           <=29
30          1  to 49
50          30 to 99
100         >=50
可以看到以查询条件a=50为例,那么锁的范围从上一个值30开始一直到下一个值100的前一个值99,这段范围都不被允许insert记录,update是可以的。 这个类似于起点和终点的概念,如果一边是开区间,那么开区间整个都会被lock
简单用3个值来表示,下面是手画的图。
间隙锁(Next-key locking)是为了防止“幻读”问题:不仅对查询中读取的行进行加锁,而且还对索引结构中的间隙(gaps)进行加锁,以防止幻影(Phantom)插入。 -- from 《高性能mysql》
This work is licensed under a CC A-S 4.0 International License.
