MySQL——锁

1 全局锁

上锁后,整个数据库处于只读状态

flush tables with read lock

释放: 

unlock tables

应用:用于全库逻辑备份

缺点:如果数据量很大,备份会花很多时间,只能读数据,造成业务停滞

如果引擎支持可重复读的隔离级别,备份之前可以先开启事务,且由于MVCC的支持,备份期间数据库仍然可以更新。 

2 表级锁

2.1 表锁

分为共享锁和独占锁,会互斥

//表级别的共享锁,也就是读锁;
lock tables t_student read;

//表级别的独占锁,也就是写锁;
lock tables t_stuent write;

 释放:

unlock tables

尽量避免使用InnoDB中的表锁,因为还有颗粒度更细的行级锁。

2.2 元数据锁 MDL

不需要显示使用MDL,对表操作时,会自动加MDL。

  • CRUD操作,加MDL读锁
  • 对表结构变更,加MDL写锁

MDL是为保证用户执行CRUD操作时,防止其它线程对表结构做变更

MDL在事务执行期间,一直持有,事务提交后释放。

MDL写锁获取优先级高于读锁,当写锁等待,后续所有CRUD操作都会被阻塞。因此,对表结构变更前,要先看看数据库中的长事务是否加了MDL读锁,如果加了读锁,后面所有操作都会被阻塞。可以考虑kill掉这个长事务。

2.3 意向锁

select 可以对记录加共享锁和独占锁,加锁之前,先对表加意向锁。

//先在表上加上意向共享锁,然后对读取的记录加共享锁
select ... lock in share mode;

//先表上加上意向独占锁,然后对读取的记录加独占锁
select ... for update;
  • 在使用 InnoDB 引擎的表里对某些记录加上「共享锁」之前,需要先在表级别加上一个「意向共享锁」;
  • 在使用 InnoDB 引擎的表里对某些纪录加上「独占锁」之前,需要先在表级别加上一个「意向独占锁」;

也就是,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的。

意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)和独占表锁(lock tables ... write)发生冲突。

作用:如果没有意向锁,加独占表锁时,就需要遍历表中所有记录,查看是否有记录存在独占锁。而有意向锁后,在对记录加独占锁之前,会对表加上意向独占锁,和独占表锁互斥。

2.4 AUTO-INC锁

主键字段声明AUTO_INCREMENT属性,可以不指定主键的值,实现自增。这是通过AUTO-INC锁实现的。

AUTO-INC锁是一种特殊的表锁,不再是一个事务提交后释放,而是执行完插入语句后就会释放。

插入数据,会加一个表级AUTO-INC锁,主键自增,其它插入语句会被阻塞,保证字段的值连续递增;插入完毕,锁释放。

但大量数据插入时,会影响性能。因此,InnoDB提供了一种轻量级的锁来实现递增。插入数据时,给主键字段赋值完毕后,锁就释放,不需要等整个插入语句执行完毕。

轻量级锁可能会导致主从数据库不一致的问题。参考小林coding.

3 行级锁

InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。

普通的 select 语句是不会对记录加锁的,因为它属于快照读。

如果要在查询时对记录加行锁,如下,这种查询会加锁的语句称为锁定读。对记录加锁前,会对表先加意向锁。

//对读取的记录加共享锁
select ... lock in share mode;

//对读取的记录加独占锁
select ... for update;

3.1 Record Lock 

记录锁,分为S锁和X锁。

共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。

3.2 Gap Lock

间隙锁,只存在于可重复读隔离级别,解决幻读现象。

假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。

间隙锁虽然存在 X 型间隙锁和 S 型间隙锁,但是并没有什么区别,间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的。

3.3 Next-Key Lock

临键锁,Record Lock + Gap Lock,锁定一个范围,并锁定记录本身。

假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。

next-key lock 是包含间隙锁+记录锁的,如果一个事务获取了 X 型的 next-key lock,那么另外一个事务在获取相同范围的 X 型的 next-key lock 时,是会被阻塞的

3.4 插入意向锁

事务插入一条记录,需要判断插入位置是否被其他事务加了间隙锁。有的话,就会阻塞,直到有间隙锁的事务提交为止,在此期间,会形成一个插入意向锁,表示想插入记录,但处于等待状态(MySQL 加锁时,是先生成锁结构,然后设置锁的状态,如果锁状态是等待状态,并不是意味着事务成功获取到了锁,只有当锁状态为正常状态时,才代表事务成功获取到了锁)。

插入意向锁并不是意向锁,是一种特殊的间隙锁,锁住的是一个点,而不是一个区间。

两个事务不能在同一时间内,一个拥有间隙锁,一个拥有间隙区间内的插入意向锁。

  • 42
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值