数据库锁一般可以分为两类,悲观锁、乐观锁 乐观锁一般指用户自己实现的锁机制,假设认为数据一般情况下不会造成冲突,类似CAS,乐观锁实现的方式一般有版本号和时间戳,悲观锁一般就是数据库层的锁机制。
Lock的精度(type)分为 行锁、表锁、意向锁
Lock的模式(mode)分为:
-
锁的类型 ——【读锁和写锁】或者【共享锁和排他锁】即 【X or S】
-
锁的范围 ——【record lock、gap lock、Next-key lock】
-
Record lock:单个行记录上的锁
-
Gap lock:间隙锁,锁定一个范围,不包括记录本身
-
Next-key lock:record+gap 锁定一个范围,包含记录本身
-
共享锁或排它锁
并不是锁的类型,而是锁的模式。
当说到共享锁 (S锁)或排它锁(X锁) ,通常是指行级锁。
表上野存在共享锁 (S锁)或排它锁(X锁),除此之外还包括意向共享锁(IS锁)和意向排它锁(IX锁)
意向锁
意向锁用来锁定层级数据结构,就是获取数据行锁之前需要先获取表的锁
意向锁的目的是告知其它事务,某事务已经锁定了某些数据行。事务在获取行锁之前首先要获取到意向锁
事务所请求的的锁与已经存在的兼容则该事务获取所请求的锁,如果存在冲突则无法获取所请求的锁
行锁的算法
Record lock 索引记录锁
锁定一个记录上的索引,而不是记录本身。
也就是索引记录锁。在某个索引的特定索引记录上设置锁
Gap lock 间隙锁
索引是B+树组织的,因此索引是从小到大按序排列的,在索引记录上查找给定记录时,InnoDB会在第一个不满足查询条件的记录上加间隙锁,防止新的满足条件的记录插入。
Next-key lock
Next-Key Lock是行锁和间隙锁的组合 :锁定索引记录以及该索引记录前面的间隙
当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)
MVCC 不能解决幻读的问题,Next-Key Locks 就是为了解决这个问题而存在的。在可重复读(REPEATABLE READ)隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。
MVCC的快照读会存在例如,一旦事务A的操作覆盖到了其他事务插入的“幻行”,那么下一次select时 也会把这行数据一起查出来 。例如事务A在第一次select时还执行了update操作对事务B插入的数据进行修改,update语句执行时,此时会先执行--当前读并且加锁, 这样在readview中数据对应的事务ID也更改了,当再次select快照读的时候修改的数据就出现了 ---幻读