MySQL 锁分类
乐观锁&悲观锁
- 乐观锁
- 认为数据一般情况下不会造成冲突,只有当数据去执行修改情况时,才会针对数据冲突做处理
- 常规的方式,都是在数据行上加一个版本号或者时间戳等字段
- 乐观锁的实现原理:
- 一个事务在读取数据时,将对应的版本号字段读取出来,假设此时的版本号是 1
- 另外一个事务也是执行同样的读取操作,当事务一提交时,对版本号执行 + 1,此时该数据行的版本号就是 2
- 第二个事务执行修改操作时,针对业务数据做条件,并默认增加一个版本号作为 where 条件,此时修改语句中的版本号字段是不满足 where 条件,该事务执行失败,通过这种方式来达到锁的功能
- 悲观锁
- 消极的一种锁处理方式,直接在操作数据时抢占锁,其他的事务在进行时就会等待,直到占有锁的事务释放锁为止
- 这种处理方式能保证数据的最大一致性,但是容易导致锁超时、并发程度低等问题
全局锁&表级锁&页级锁&行级锁
- 全局锁
- 全局读锁的方法,命令是 Flush tables with read lock;
- 需要让整个库处于只读状态的时候,可以使用这个命令
- 之后其他线程的以下语句会被阻塞:
- 数据更新语句(数据的增删改)
- 数据定义语句(包括建表、修改表结构等)
- 更新类事务的提交语句
- 表级锁
- 锁定粒度比较大的一种锁,针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁
- 锁定粒度比较大,触发锁冲突的概率最高,并发度最低,MyISAM 和 InnoDB 引擎都支持表级锁
- 页级锁
- 页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之 间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也介于表级锁和行级锁中间
- 使用页级锁定的主要是 BerkeleyDB 存储引擎
- 行级锁
- MySQL的行锁是在引擎层由各个引擎自己实现的,不是所有的引擎都支持行锁,比如 MyISAM 引擎就不支持行锁
- 行锁就是针对数据表中行记录的锁,比如事务A更新了一行,而这时候事务B也要更新同一行,则必须等事务A的操作完成后才能进行更新
- 行锁是针对数据库表中行记录的锁,是锁一行或者多行;MySQL 的行锁是基于索引加载的,所以行锁是要加在索引响应的行上,InnoDB 的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话,行锁锁定的也是整张表,锁整张表会造成程序的执行效率会很低;加行锁的目的是为了减少锁冲突,提升业务的并发度
- MySQL InnoDB 支持三种行锁定方式:
- 记录锁(Record Lock):也被称为记录锁,属于单个行记录上的锁
- 间隙锁(Gap Lock):锁定一个范围,不包括记录本身
- 临键锁(Next-key Lock):Record Lock + Gap Lock,锁定一个范围,包含记录本身;记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁
共享锁&排它锁
- InnoDB 实现如下两种标准的行锁
- 共享锁(Share Lock,S):又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)
- 排它锁(Exclusive Lock,X):又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取,如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)
- 共享锁和排它锁兼容性
- 排它锁与任何的锁都不兼容,共享锁仅和共享锁兼容
- 可以通过以下语句显式加共享锁或排他锁:
- 共享锁:
SELECT ... LOCK IN SHARE MODE;
- 排他锁:
SELECT ... FOR UPDATE;
- 共享锁:
- MVCC 的存在,对于一般的 SELECT 语句,InnoDB 不会加任何锁
S锁 | X锁 | |
---|---|---|
S锁 | 不冲突 | 冲突 |
X锁 | 冲突 | 冲突 |
意向共享锁&意向排它锁
- 意向锁的作用
- 如果需要用到表锁的话,如何判断表中的记录没有行锁呢?一行一行遍历肯定是不行,性能太差,我们需要用到一个叫做意向锁的东东来快速判断是否可以对某个表使用表锁
- 意向锁是表级锁
- 意向共享锁(Intention Shared Lock,IS 锁):事务有意向对表中的某些加共享锁(S 锁),加共享锁前必须先取得该表的 IS 锁
- 意向排他锁(Intention Exclusive Lock,IX 锁):事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的 IX 锁
- 意向锁由数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享/排他锁之前,InnoDB 会先获取该数据行所在在数据表的对应意向锁
- 意向锁之间是互相兼容的
IS 锁 | IX 锁 | |
---|---|---|
IS 锁 | 兼容 | 兼容 |
IX 锁 | 兼容 | 兼容 |
- 意向锁和共享锁和排它锁互斥
IS锁 | IX锁 | |
---|---|---|
S锁 | 兼容 | 互斥 |
X锁 | 互斥 | 互斥 |
记录锁&间隙锁&临键锁
- 记录锁(Record Lock):也被称为记录锁,属于单个行记录上的锁
- 间隙锁(Gap Lock):锁定一个范围,不包括记录本身
- 临键锁(Next-key Lock):Record Lock + Gap Lock,锁定一个范围,包含记录本身;记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁