MySQL锁机制

MySQL的锁分为三类:全局锁、表锁、行锁。

全局锁

使用

下面的这条指令可以加全局锁:

flush tables with read lock

执行完后,数据库就处于只读状态,其他的操作都会阻塞。

释放全局锁:

unlock tables

        全局锁主要应用于做全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。

一般也不推荐这样加全局锁,因为会阻塞其他的操作,建议使用工具mysqldump:

如果数据库的引擎支持的事务支持可重复读的隔离级别,

那么在备份数据库之前先开启事务,会先创建 Read View,然后整个事务执行期间都在用这个 Read View,而且由于 MVCC 的支持,备份期间业务依然可以对数据进行更新操作。

因为在可重复读的隔离级别下,即使其他事务更新了表的数据,也不会影响备份数据库时的 Read View,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。

备份数据库的工具是 mysqldump,在使用 mysqldump 时加上 –single-transaction 参数的时候,就会在备份数据库之前先开启事务。这种方法只适用于支持「可重复读隔离级别的事务」的存储引擎。

InnoDB 存储引擎默认的事务隔离级别正是可重复读,因此可以采用这种方式来备份数据库。

但是,对于 MyISAM 这种不支持事务的引擎,在备份数据库时就要使用全局锁的方法。

表级锁

MySQL是表级锁有四类:表锁、元数据锁、意向锁、AUTO-INC 锁

表锁

如果想对表加锁:

写锁
lock tables table_name read

读锁
lock tables table_name write

需要注意的是,表锁除了会限制别的线程的读写外,也会限制本线程接下来的读写操作。

释放锁:

unlock tables

元数据锁(MDL)

我们不需要显示的使用 MDL,因为当我们对数据库表进行操作时,会自动给这个表加上 MDL:

  • 对一张表进行 CRUD 操作时,加的是 MDL 读锁;
  • 对一张表做结构变更操作的时候,加的是 MDL 写锁;

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

MDL 是在事务提交后才会释放,这意味着事务执行期间,MDL 是一直持有的。

申请 MDL 锁的操作会形成一个队列,队列中写锁获取优先级高于读锁,一旦出现 MDL 写锁等待,会阻塞后续该表的所有 CRUD 操作。

为了能安全的对表结构进行变更,在对表结构变更前,先要看看数据库中的长事务,是否有事务已经对表加上了 MDL 读锁,如果可以考虑 kill 掉这个长事务,然后再做表结构的变更。

意向锁

在使用 InnoDB 引擎的表里对某些记录加上「共享锁」或者 「独占锁」之前,需要先在表级别加上一个「意向共享锁」或者 「意向独占锁」;

也就是,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。

而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的

想要select语句也加锁,可以按以下方式:

写锁(共享锁)
select ***  lock in share mode 

读锁(独占锁)
select *** for update
  

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

表锁与行锁是满足读读共享、读写互斥、写写互斥的。

意向锁主要提高加表锁的效率,如果没有意向锁,然后又需要加上表锁,就需要每一条记录的检查是否加了行锁,效率很低。

行级锁

Innodb支持行级锁,MyIASM不支持行级锁。

行锁主要有三类:

  • 记录锁(Record Lock):仅仅把一条记录锁上
  • 间隙锁(Gap Lock):锁定一个范围,但是不包含记录本身
  • 临键锁(Next-Key Lock):Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身

记录锁

记录锁是有共享锁和独占锁之分的:

begin;

select * from t_test where id = 1 for update;

对id为1的记录加了独占锁,直到commit才释放。

​​​​​​​

间隙锁

只存在与可重复读级别,目的是为了解决可重复读隔离级别下的幻读问题。

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

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

临键锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值