自增锁
自增锁是一种特殊的表级别锁(table-level lock),专门针对事务插入 AUTO_INCREMENT 类型的列。最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。
查询当前数据库的自增锁模式:
show variables like '%innodb_autoinc_lock_mode%';
共享锁和排它锁
共享锁
共享锁(Shared Locks)简称为 S 锁。读取数据时候可以加 S 锁。
共享 (S) 锁允许并发事务读取 (SELECT) 一个资源。资源上存在共享 (S) 锁时,任何其它事务都不能修改数据。一旦已经读取数据,便立即释放资源上的共享 (S) 锁,除非将事务隔离级别设置为可重复读或更高级别,或者在事务生存周期内用锁定提示保留共享 (S) 锁。
排它锁
排它锁 (Exclusive Locks)简称为 X 锁。修改数据时候加 X 锁。
排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能读取或修改排它 (X) 锁锁定的数据。
共享锁之间可以并行,排它锁和共享锁之间互斥,也就是说只要共享锁开启没有释放掉的时候,更新锁是不能抢占的,此时其他读取同资源的操作可以进行读取不受限制;同理排它锁开启时候只要没有释放其他不管是排它锁还是共享锁都不可以抢占资源直到锁释放。
读资源的时候大家一起读没问题,影响不了什么,
但是我读的时候,你不能修改呀,这样我不就读到错的了吗,所以读的时候不许修改,
那我在修改的时候,你也不许读啊,谁知道你会不会读到错的呢,所以修改的时候不能读。
意向锁(Intention Locks; table-level lock)
意向锁是一种特殊的表级锁,意向锁是为了让 InnoDB 多粒度的锁能共存而设计的。取得行的共享锁和排他锁之前需要先取得表的意向共享锁(IS)和意向排他锁(IX),意向共享锁和意向排他锁都是系统自动添加和自动释放的,整个过程无需人工干预。
意向共享锁(Intention Shared Lock) IS
事务有意向对表中的某些行加共享锁(S锁)
意向排它锁(Intention Exclusive Lock)IX
事务有意向对表中的某些行加排他锁(X锁)
举例
-- 要设置 IS 锁 --
-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
select * from A where id = 1 lock in share mode;
-- 要设置 IX 锁 --
-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
select * from A where id > 0 for update;
看上面那个例子,如果示例 1 和 2 都开启了事务,事务 1 锁住了表 A 的其中 id=1 的一行,事务 2 要获取整个表的更新锁需要进行判断
step1:判断表 A 是否有表级锁
step2:判断表 A 每一行是否有行级锁
当数据量庞大的时候 step2 这种判断十分低效,于是就有意向锁协议
意向锁协议:
事务要获取表 A 某些行的 S 锁必须要获取表 A 的 IS 锁
事务要获取表 A 某些行的 X 锁必须要获取表 A 的 IX 锁
这时候 step2 就改变成了对意向锁的判断
step2:发现表 A 有 IS 锁,说明表 A 肯定有行级的 S 锁,因此,事务 B 申请写锁阻塞等待,判断效率极大提高
记录锁
SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;
这一行则是使用了记录锁,不允许其他事务进行增,删,改
但是 SELECT c1 FROM t WHERE c1 = 10;
是没有锁的,走的是快照读
记录锁本身不是锁定记录数据本身而是锁定索引记录,如果要锁的列没有索引,则会进行全表记录加锁
间隙锁
比如 SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;
插入 c1 为 15 的记录会被锁定不可执行
这种默认存在于可重复读的事务隔离级别中的锁,锁定被圈定的范围不允许 insert,防止不可重复读,上文说了我们的事务隔离级别都是读已提交,默认会产生不可重复读的问题
临键锁
插入意向锁
参考文章:[https://www.cnblogs.com/detectiveHLH/p/14805898.html]
btw,lintcode的锁讲的和史一样