一.简介
悲观锁:在读取数据时锁住那几行,其他对这几行的更新需要等到悲观锁结束时才能继续 。
乐观锁:读取数据时不锁,更新时检查是否数据已经被更新过,如果是则取消当前更新,一般在悲观锁的等待时间过长而不能接受时我们才会选择乐观锁。
InnoDB行锁实现方式:InnoDB行锁是通过给索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录枷锁。
- 共享锁(S):允许一个事务去读取一行,阻止其他事务获取相同数据集的排他锁。
- 排他锁(X):允许获得排他锁的事务更新数据,组织其他事务获取相同数据集的共享锁和排他锁。
for update是在数据库中上锁用的,可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。
for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。
要测试for update的锁表情况,可以利用MySQL的Command Mode,开启二个视窗来做测试。
二.for update行级锁和表锁的几种情况
1.明确指定主键/索引,并且有此记录,行级锁
2.未指定主键/索引,并且有此记录,表级锁
3.当我们使用范围条件而不是相等条件检索数据并请求共享锁或排他锁时,InnoDB会给条件已有数据记录的索引项加锁,对于键值在条件范围但不存在的记录加间隙锁
4.明确指定主键/索引,若查无此记录,加间隙锁
5.无主键/索引,表级锁
6.主键/索引不明确,表级锁
三.测试
开2个窗口测试:
// 执行 代码片段一
BEGIN ; //开始事务
SELECT userName FROM user WHERE userId = 1 FOR UPDATE;
// 执行 代码片段二
BEGIN ; //开始事务
SELECT userName FROM user WHERE userId = 1 FOR UPDATE;
update user set userName='sun' where userId = 1;
先执行代码片段一。再执行代码片段二。