共享锁与排它锁
在InnoDB存储引擎中,存在两种锁,即共享锁lock in share mode与排它锁for update,这两种锁全部行级锁,而且此两种锁是加在了索引项上,如果索引失效了,那么此两种锁会膨胀为表级锁(MyISAM默认为表级锁)。
说到这两种锁,其实这在代码层只不过是一个标记,以for update举例,如果某一个事务的SQL携带了for update,他在底层会做的就是先检测其它事务是否持有该锁,如果不持有,则加锁,如果持有,则等待其它事务释放该锁。
lock in share mode
之所以称之为共享锁,因为它被一个事务获取到后,其它事务还可以接着获取他,只不过,另一个获取到他的事务不可以对其进行CUD操作,只能进行读操作。
而第一个获取到他的事务可以进行CUD操作,但这是不被建议的,这可能会引发死锁。
InnoDB存储引擎处理死锁的办法就是让一个事务停止等待(选择持有行级锁最少的事务放弃等待)
注意,此时对该事务加的是共享锁,且并没有提交事务。

再打开一个查询窗口,同样尝试获得该锁,发现可以获得。
尝试在新的查询窗口中执行CUD操作,等待一段时间后发现获取锁超时,证明在其他事务中不可以修改s锁
那么如果在其他的查询语句中不手动加lock in share mode呢,会怎么样,可以不以执行呢
发现是可以执行的,其实在上一步去执行修改的操作时大家也看到了,并没有手动的加s锁,只不过在执行CUD操作时,默认会加x锁(for update)。加了s锁后,是不允许其它事务对此加x锁的,所有形成了等待超时的错误。
上面说了,无论是x锁还是s锁,在SQL代码里只不过是一个标记而已,持有该标记的SQL在底层执行时会去检测,如果没有携带该标记的SQL在底层执行是就不会检测(CUD操作除外)。此原理会在for update演示中介绍。
for update
即排它锁,在一个事务中如果加了x锁,则不允许其它事务进行CRUD操作,也不允许其它事务对其加s锁,需要等待当前事务释放该x锁后,方可一切正常。
对该事务加x锁
其它事务进行查询操作,发现查询被阻塞,并没有查询出来数据
但是不加for update,则可以查询成功,这就是上面所说的标记问题,没有加标记,那么我就完全可以不遵循约定,我就不用等待,直接就可以拿到结果
同样是这种问题,CUD操作不加for update,也是可以会被阻塞的,原因上面也说了,CUD操作默认加x锁

说明
上面举的例子中有的直接使用了SQL语句,并没有开启事务,这样是被允许的,只要设置了autocommit = 1,则自动提交事务,执行单独的SQL时,开始时隐式的开启了事务,执行完毕后,又隐式的提交了事务。
锁与事务其实并没有关系,之所以把x锁或s锁写在事务里,是因为增大作用域,这样便于测试,如果在一定的条件下同时执行下列SQL语句,也会引发等待。
select id from student for update;
select s_sex from student for update;