一、锁的定义:
高并发下会出现抢占公共资源的情况,锁是为了保证数据读取、修改的一致性
二、锁的粒度、类型、并发能力、占用资源
(1) 类型:共享锁(S Lock也叫读锁)、排他锁(X Lock也叫写锁)
这里还有个意向锁,意向锁可以理解成多个锁的意思。例如:意向共享锁(IS Lock),给多个记录加上S Lock,意向排他锁(IX Lock),给多个记录加上X Lock。
(2) 锁的粒度: 表锁、页锁、行锁、间隙锁(Gap Lock、Next-key Lock)
间隙锁意思是一个范围的锁(高中数学的区间概念),例如锁定的范围是(2,+∞)。Gap Lock是不包括当前记录本身,所以它的区间是开区间。Next-key Lock是包括记录本身,即[2,+∞)。间隙锁是INNODB(默认隔离级别:Repeatable-Read可重复读)解决幻读的一个方法。
间隙锁会在一定范围内上X锁,这样别的事务Insert的时候需要阻塞(等待),等待间隙锁的释放
间隙锁要在两个隔离级别中使用,分别是(Read-Committed已提交读和Repeatable-Read可重复读)
间隙锁会出现在非唯一索引上,唯一索引会使用行锁
Oracle、SQL Server(默认的事务隔离等级是Read-Committed)
MYSQL的INNODB(默认隔离级别:Repeatable-Read)
MYSQL的MYSIAM存储引擎是表锁
Oracle支持页锁
MYSQL的INNODB存储引擎支持行锁
(3) 并发能力:
表锁 < 页锁 < 行锁
(4) 占用资源
表锁 < 页锁 < 行锁
对于行锁来说,锁住一行跟锁住N行,占用资源(内存)是一样的
三、锁的兼容情况
(1) S锁和X锁
| S Lock | S Lock | |
| S Lock | 兼容 | 不兼容 |
| X Lock | 不兼容 | 不兼容 |
A事务去读取id=1的数据,此时B事务也可以去读取,其余情况都会出现阻塞的情况
(2) IS锁、IX锁、S锁、X锁
| IS Lock | IX Lock | S Lock | X Lock | |
| IS Lock | 兼容 | 兼容 | 兼容 | 不兼容 |
| IX Lock | 兼容 | 兼容 | 不兼容 | 不兼容 |
| S Lock | 兼容 | 不兼容 | 兼容 | 不兼容 |
| X Lock | 不兼容 | 不兼容 | 不兼容 | 不兼容 |
四、死锁
(1) 定义:两个或两个以上的事务在执行过程中,因争夺锁资源而产生的一种相互等待的现象
(2) 解决方式:
a:设置锁的等待时长:innodb_lock_wait_timeout
查看本地的锁等待时长:
SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout';
设置锁的等待时长:
SET GLOBAL innodb_lock_wait_timeout = 500;
设置等待时长的目的是让其中一个事务回滚,另一个事务可以继续执行
b:wait-for graph 等待图

同一时刻有t1,t2,t3,t4四个事务同时进行
t1事务等待t2释放row1的资源
t2事务等待t1,t4释放的row2的资源

事务t1和事务t2存在回路,会产生死锁
五、查看事务、锁、锁等待情况
(1) 查看事务执行情况
SELECT * FROM information_schema.INNODB_TRX\G;

看到当前有个id:42100的事务
(2) 查看锁的情况
SELECT * FROM information_schema.INNODB_LOCKS;

参数:
lock_id 锁id
lock_trx_id 事务id
lock_type 锁的类型(行锁or表锁)
lock_mode 锁的模式(S锁orX锁)
lock_table 加锁的表
lock_index 加锁的索引
lock_space 加锁对象的space_id
lock_page 锁定页的数量
lock_rec 事务锁定的行数
lock_data 事务锁定的主键值(这里看到的不一定是准确的,如果锁定的是多个主键的话,这里还是显示一个)
(3) 查看锁的等待情况
SELECT * FROM information_schema.INNODB_LOCK_WAIT\G;

参数:
blocking_trx_id 获得锁(阻塞)的事务id
blocking_lock_id 获得锁(阻塞)的锁id
requesting_trx_id 请求锁(等待锁)的事务id
requesting_lock_id 请求锁的锁id
六、一致性非锁定读