手记

mysql数据库锁简介

本篇介绍有关数据库锁相关的知识,关于数据库事务及隔离级别参见《数据库事务ACID特性及隔离级别》这篇文。

 

乐观锁

乐观锁最常用的实现方式是用数据版本(Version)记录机制。数据版本即为数据增加一个版本标识,一般通过在数据库表中增加一个数字类型的 “version” 字段实现。读取数据时将version字段值一同读出,数据每更新一次,对version值加1,提交更新时将数据库表对应记录的当前version值与已取出的version值进行比对,如果数据库表当前version值与已取出的version值相等,则可以更新,否则认为是过期数据。

 

通常在实际项目中涉及金钱类的可能会使用这种乐观锁。

 

举例:

1、数据库表三个字段,分别是id、value、version

select id,value,version from table1 where id = #{id}

2、每次更新表中的value字段时为了防止发生冲突,需要这样操作

update table1

set value=2,version=version+1

where id=#{id} and version=#{version}

 

悲观锁

悲观锁认为在操作数据时会出现数据冲突,每次都要通过获取锁才能对相同数据进行操作,所以悲观锁需要耗费较多的时间。共享锁 和 排它锁 是悲观锁的不同实现,都属于悲观锁的范畴。

 

1、锁的粒度

 

InnoDB默认采用行锁,在未使用索引字段查询时升级为表锁。行锁可能因为未使用索引而升级为表锁,所以除了检查索引是否创建的同时,也需要通过explain执行计划查询索引是否被实际使用。

 

2、读写锁

3、意向锁(Intention Locks)

为了实现多粒度锁机制,协调 行级读写锁 和 表级读写锁 (也就是不同粒度)之间的关系。意向锁是一种允许 行锁 与 表锁 共存的表锁。意向锁是由数据库引擎维护的,用户无法手动操作。在为数据行加 共享锁 / 排它锁 之前,InooDB 会先获取该数据行所在数据表的对应 意向锁。意向锁只会阻塞全表请求,主要目的是展示正在锁定表中一行,或者将要锁定一行。

 

意向锁分为两种:

 

意向共享锁(intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁)

-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。

SELECT column FROM table1 ... LOCK IN SHARE MODE;

 

意向排它锁(intention exclusive lock, IX):事务有意向对表中的某些行加排它锁(X锁)

-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。

SELECT column FROM table1 ... FOR UPDATE;

 

意向锁不会与行级的 共享/排它锁 互斥。

1) InnoDB 支持多粒度锁,特定场景下,行级锁 可以与 表级锁 共存。

2) 意向锁之间互不排斥,但除了 IS 与 S 兼容外,意向锁会与 共享锁 / 排它锁 互斥。

3) IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。

4) 意向锁在保证并发性的前提下,实现了行锁和表锁共存且满足事务隔离性的要求。

 

4、记录锁(Record Locks)

记录锁是在索引记录上的锁。例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 防止任何其他事务 插入、更新 或 删除 t.c1=10 的行。

 

5、间隙锁(Gap Locks)

间隙锁(gap)是索引记录之间上的锁,或者说第一个索引记录之前或最后一个索引记录之后的间隔上的锁。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; 阻止其他事务插入 t.c1 = 15 的记录,不管是否已经有这种值在本列中,因为这个范围内的所有值都被上锁了。

 

6、NK锁(Next-Key Locks)

NK锁是记录锁和间隙锁的组合,锁定一个范围,并且锁定记录本身。对查询范围进行加锁,在另一个事务执行插入操作时是不被运行的,从而避免了幻读。用于解决幻读问题。

 

InnoDB默认的事务隔离级别是Repeatable Read,此时InnoDB使用NK锁进行搜索和索引扫描,防止产生幻读。

 

7、插入意向锁(Insert Intention Locks)

插入意向锁是在插入一条记录行前,由 INSERT 操作产生的一种间隙锁。该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待。

 

插入意向锁本质上可以看成是一个间隙锁(Gap Lock)。

 

普通的Gap Lock 不允许 在(上一条记录,本记录)范围内插入数据

插入意向锁Gap Lock 允许 在(上一条记录,本记录)范围内插入数据

 

插入意向锁的作用是为了提高并发插入的性能, 多个事务 同时写入 不同数据 至同一索引范围(区间)内不需要等待其他事务完成,不会发生锁等待。

 

InnoDB 在 Repeatable Read 的事务隔离级别下,使用插入意向锁来控制和解决并发插入。

 

8、自增锁(AUTO-INC Locks)

自增锁是由插入到具有AUTO_INCREMENT列的表中的事务所采用的特殊表级锁。 在最简单的情况下,如果一个事务正在向表中插入值,任何其他事务必须等待,以便这个事务获得连续的主键值。

作者:AIData

原文出处:https://www.cnblogs.com/aiandbigdata/p/10488308.html  

0人推荐
随时随地看视频
慕课网APP