技巧💡

锁,是为了应对资源竞争的解决方案,为了提高效率, 可以分为读写锁。读读不互斥,读写互斥。

分类

加锁机制

乐观锁,根据版本号控制
悲观锁,锁定表或者行,让其他数据操作等待。

锁粒度

表级锁

技巧💡

  1. 元数据锁(Metadata Lock,MDL
    1.1 当对一个表做增删改查的时候,该表会被加MDL读锁
    1.2 当对表做结构变更的时候,加MDL写锁
  2. 意向锁
  3. 表锁, lock table

表锁偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低
当前session对该表的增删改查都没有问题,其他session对该表的所有操作被阻塞。

myisam在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。
1、对MyISAM表的读操作(加读锁) ,不会阻寒其他进程对同一表的读请求,但会阻赛对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
2、对MylSAM表的写操作(加写锁) ,会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作总结:
简而言之,就是读锁会阻塞写,但是不会阻塞读。而写锁则会把读和写都阻塞

lock table表名称 read(write)  
unlock tables

行级锁

行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。InnoDB与MYISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。

技巧💡

  1. 针对当前读,innoDB交互是一条一条的进行,加锁也是一条一条.
  2. 快照读是不加锁的。通过索引+mvcc 实现。所以加锁,本质上是锁索引
  3. 当前读实际上是一种加锁的操作,是悲观锁的实现

根据行级锁锁的范围,包含了

  • 记录锁,锁记录
  • 间隙锁,锁期间
  • Next-key Lock(默认),既包含索引记录,又包含索引区间.

页面锁(主要是BerkeleyDB存储引擎使用页面锁)

开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

兼容性

读锁(共享锁, Share) 针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(排他锁),当前写操作没有完成前,它会阻断其他写锁和读锁。

锁模式

记录锁, 锁行
间隙锁, 锁区间。
临键锁,既包含索引记录,又包含索引区间.
意向锁,锁

一条简单SQL的加锁实现分析

死锁