1 Lock与Latch
Latch:
Latch又可以分为mutex(互斥量)和rwlock(读写锁)。
其目的是用来保证并发线程操作临界资源的正确性
Lock:
Lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。
2 锁的类型
InnoDB行级锁:
包含共享锁(Shared Lock)和互斥锁(Exclusive Lock)
共享锁(读锁),允许事务读一行数据。
排他锁(写锁),允许事务删除或更新一行数据。
特点:
共享锁之间是兼容的,而互斥锁与其他任意锁都不兼容:
因为共享锁代表了读操作、互斥锁代表了写操作,所以我们可以在数据库中并行读,但是只能串行写。
3 锁的粒度
Lock锁根据粒度主要分为表锁、页锁和行锁。
3.1 表锁
由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。
3.2 页锁
页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间
3.3 行锁
发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力
使用行级锁定的主要是InnoDB存储引擎。
表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;
而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,
如一些在线事务处理(OLTP)系统。
3.4 意向锁
作用:
如果没有意向锁,当已经有人使用行锁对表中的某一行进行修改时,如果另外一个请求要对全表进行修改,
那么就需要对所有的行是否被锁定进行扫描,在这种情况下,效率是非常低的;
不过,在引入意向锁之后,当有人使用行锁对表中的某一行进行修改之前,会先为表添加意向互斥锁(IX),
再为行记录添加互斥锁(X),在这时如果有人尝试对全表进行修改就不需要判断表中的每一行数据是否被加锁了,
只需要通过等待意向互斥锁被释放就可以了。
种类:
意向共享锁(IS):事务想要在获得表中某些记录的共享锁,需要在表上先加意向共享锁。
意向互斥锁(IX):事务想要在获得表中某些记录的互斥锁,需要在表上先加意向互斥锁。
意向锁其实不会阻塞全表扫描之外的任何请求,它们的主要目的是为了表示是否有人请求锁定表中的某一行数据。
3.5 行锁
种类:
Record Lock:单个行记录上的锁。
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。
Record Lock总是会去锁住索引记录.
Next-Key Lock是结合了Gap Lock和Record Lock的一种锁定算法,
在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。
Gap Lock的作用是为了阻止多个事务将记录插入到同一个范围内,
设计它的目的是用来解决Phontom Problem(幻读问题)。
在MySQL默认的隔离级别(Repeatable Read)下,InnoDB就是使用它来解决幻读问题。
幻读是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL可能会返回之前不存在的行,
也就是第一次执行和第二次执行期间有其他事务往里插入了新的行。
3.6 一致性非锁定读
是指InnoDB存储引擎通过多版本控制(MVCC)的方式来读取当前执行时间数据库中行的数据。如果读取的这行正在执行DELETE或UPDATE操作,
这时读取操作不会向XS锁一样去等待锁释放,而是会去读一个快照数据。
3.7 一致性锁定读
默认隔离级别RR下,InnoDB存储引擎的SELECT操作使用一致性非锁定读。但是在某些情况下,用户需要显式地对数据库读取操作进行加锁以保证数据逻辑的一致性。
InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作。
SELECT … FOR UPDATE (X锁)
SELECT … LOCK IN SHARE MODE (S锁)
4 死锁
死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象
参考:
MySQL技术内幕InnoDB存储引擎
http://benjaminwhx.com/2018/04/27/%E8%B0%88%E8%B0%88MySQL%E7%9A%84%E9%94%81/