1、记录锁:即锁住记录本身
2、间隙锁:锁住一段没有记录的间隙,可以是两条记录的中间部分,也可以是第一条记录的前置部分或最后一条记录的后续部分
3、next-key锁:是记录锁与间隙锁的结合,特点为左开右闭,如(4,10],由间隙锁(4,10)和记录锁idx = 10组成
>和<:若起始索引记录不存在,则锁住起始索引所在间隙及后续记录和间隙;若存在,则从起始索引记录(不包含)开始,锁住范围内的记录和间隙
>=:若起始索引不存在,则锁住起始索引记录所在间隙以及后续记录和间隙,若存在,则从起始索引记录(包含)开始,锁住范围内所有的记录和间隙
<=:若起始索引不存在,则锁住起始索引所在间隙与后续的记录和间隙,若存在,则从起始索引记录开始,锁住范围内记录和间隙,并锁住起始索引另一侧的间隙,验证如下:
如下表:表名为foo,uid为主键索引,也即唯一索引,idx为普通索引
+-----+-----+------+
| uid | age | idx |
+-----+-----+------+
| 1 | 1 | 1 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
| 10 | 10 | 10 |
| 16 | 16 | 16 |
+-----+-----+------+
事务A:执行select * from foo where uid >= 10 and uid <= 16 for update;
事务B:执行insert into foo values(9,9,9);
事务C:执行update foo set age = 5 where uid = 4;
事务D:执行insert into foo values(17,17,17);
其中事务B和C成功执行,事务D阻塞,分析可得[16, 正无穷)被锁住,而[4,10)未被锁住
若是事务A修改为:select * from foo where uid >= 10 and uid < 16 for update;
则事务D不会被阻塞,也即(16,正无穷)未被锁住
事务加锁时,其他事务进行写操作时会受到阻塞,这个阻塞时间当然是越短越好,那么对于一个事务当中不同需要加锁的语句,可以采用以下方式控制:
举个两个简单例子,来自MySQL实战45讲
1、用户A、B要到影院C购票,需要进行以下操作:
分析业务,容易得出影院的记录是热点记录,相较用户记录更改频繁,因此可以将影院操作语句放在事务后面,减少影院记录上锁时间
2、删除一个表中的前10000条数据,给出三种方案,那种最合适
答案是第三种,原因如下
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦