一、表级锁、行级锁、页级锁
数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则。
MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。
MySQL各存储引擎使用了三种级别的锁定机制:表级锁定,行级锁定和页级锁定。
1、表级锁
表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。
当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并发度大打折扣。
使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。
2、行级锁
行级锁定最大的特点就是锁定对象的颗粒度很小,由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。
由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。
使用行级锁定的主要是InnoDB存储引擎。
3、页级锁
页级锁定是MySQL中比较独特的一种锁定级别。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。
使用页级锁定的主要是BerkeleyDB存储引擎。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
二、共享锁、排它锁
InnoDB 实现了标准的行级锁,包括两种:共享锁(简称 s 锁)、排它锁(简称 x 锁)。
对当前行加共享锁,不会阻塞其他事务对同一行的读请求,但会阻塞对同一行的写请求。
只有当读锁释放后,才会执行其它事物的写操作。
对当前行加排它锁,会阻塞其他事务对同一行的读和写操作,只有当写锁释放后,才会执行其它事务的读写操作。
兼容性 | 共享锁(S) | 排它锁(X) |
---|---|---|
共享锁(S) | 兼容 | 不兼容 |
排它锁(X) | 不兼容 | 不兼容 |
InnoDB 在RR(MySQL默认隔离级别) 隔离级别时,对于 update、delete 和 insert 语句, 会自动给涉及数据集加排它锁(X);普通 select 语句,innodb 不会加任何锁。如果想在select操作的时候加上 S锁 或者 X锁,需要我们手动加锁。
-- 加共享锁(S)
SELECT * FROM T WHERE ... lock in share mode
-- 加排它锁(X)
SELECT * FROM T WHERE ... for update
三、记录锁(Record Locks)
记录锁其是对表中的记录加锁,叫做记录锁,简称行锁。比如
SELECT * FROM T WHERE ID = '1' for update
update set a = '1' where ID = '1'
它会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行。
- id必须为主键或唯一索引,否则锁会退化成临键锁
- 查询语句必须为精度匹配(=),不能为>,<,like等,也会退化成临键锁
四、间隙锁(Gap Locks)
间隙锁是行锁的一种,是Innodb在RR(可重复读)隔离级别下为了解决幻读引入的锁机制
间隙锁锁的是一个区间,而不仅仅是锁这个区间中的每条数据
例:有id为1、2、3…10、11
selet * from T where id > 10 for update
以上查询不仅会锁住id为11的数据,也会大于10的整个区间进行加锁,如果要插入id为12的数据会无法插入