mysql锁

1.全局锁

//加全局锁
flush tables with read lock

//释放全局锁
unlock tables

执行后,整个数据库就处于只读状态,加上了全局锁。全局锁颗粒度比表级锁大,此时所有线程对表结构、表数据只能执行读了。

当然,如果当前加全局锁的会话断开,全局锁会被自动释放。

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

2.表级锁

2.1表锁

//表级别的共享锁,也就是读锁;
//允许当前会话读表,阻止其他会话写表。同时本会话不能访问其他表
lock tables student read;

//表级别的独占锁,也就是写锁;
//允许当前会话对表进行读写操作,阻止其他会话对表进行任何操作(读或写)。
lock tables student write;

2.2意向锁

当要使用表锁时,如何判断表中的记录没有行锁呢,一行一行遍历肯定是不行,性能太差。要用意向锁来快速判断是否可以对某个表使用表锁。

  • 意向共享锁(Intention Shared Lock,IS 锁):事务有意向对表中的某些记录加共享锁(S 锁),加共享锁前必须先取得该表的 IS 锁。
  • 意向排他锁(Intention Exclusive Lock,IX 锁):事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的 IX 锁。

意向锁之间兼容,与行级的共享锁和排他锁兼容,但是和表级的共享锁和排他锁互斥。
所以说当执行增、删、改操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。

另外当前读的select也会加共享锁、独占锁。

3.行锁

3.1间隙锁

间隙锁是一种加在两个索引之间的锁,锁的是一个开区间只存在于可重复读隔离级别。

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

临建锁和间隙锁在幻读中的使用场景

详解 MySql InnoDB 中的三种行锁(记录锁、间隙锁与临键锁) - HappyDeveloper - 博客园

  • 使用间隙锁的情况

    • 非唯一索引的等值查询:例如SELECT * FROM table WHERE non_unique_col = 5 FOR UPDATE,若5存在,会锁定5周围的间隙;若5不存在,则锁定其应存在的间隙。

    • 范围查询:如WHERE id > 10,若未命中记录,会锁定符合条件的间隙。

    • 唯一索引的等值查询(未命中):如SELECT * FROM table WHERE unique_col = 15 FOR UPDATE,当15不存在时,锁定其所在的间隙。

  • 临键锁触发条件

    • 非唯一索引的范围查询:如WHERE non_unique_col BETWEEN 5 AND 10

    • 唯一索引的范围查询:如WHERE unique_col > 10

    • 默认锁机制:在可重复读级别下,InnoDB默认对索引扫描使用临键锁

3.2记录锁

记录锁是最简单的行锁,仅锁住一行,有读锁和写锁之分,读写锁互斥。

如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE

如果C1字段是主键或者是唯一索引的话,这个SQL会加一个记录锁,记录锁永远都是加在索引上的,即使一个表没有索引,InnoDB也会隐式的创建一个索引,并使用这个索引实施记录锁。它会阻塞其他事务对这行记录的插入、更新、删除。

3.3临键锁

Next-key锁是记录锁和间隙锁的组合解决了锁定读的幻读问题(非锁定读用快照读即可解决幻读),它指的是加在某条记录以及这条记录前面间隙上的锁。说得更具体一点就是:临键锁会封锁索引记录本身,以及索引记录之前的区间,即它的锁区间是左开右闭,比如 (5,10]

在 InnoDB 默认的隔离级别 可重复读 下,行锁默认使用的是临键锁。但是,如果操作的索引是唯一索引或主键,InnoDB 会对临键锁进行优化,将其降级为 记录锁 ,即仅锁住索引本身,而不是范围。

3.4自增锁(表级锁)

专门针对AUTO_INCREMENT类型的列,对于这种列,如果表中新增数据时就会去持有自增锁。简言之,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。

3.5插入意向锁

假设事务 A 已经对表加了一个范围 id 为(3,5)间隙锁。

当事务A还没提交的时候,事务B向该表插入一条id=4的新记录,这时会判断到插入的位置已经被事务A加了间隙锁,于是事物B会生成一个插入意向锁,然后将锁的状态设置为等待状态(PS:MySQL加锁时,是先生成锁结构,然后设置锁的状态,如果锁状态是等待状态,并不是意味着事务成功获取到了锁,只有当锁状态为正常状态时,才代表事务成功获取到了唢,此时事务B就会发生阻塞,直到事务A提交了事务。

行级锁和表级锁对比

  • 表级锁: MySQL 中锁定粒度最大的一种锁(全局锁除外),是针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。
  • 行级锁: MySQL 中锁定粒度最小的一种锁,是 针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的。
  • InnoDB 的行锁是针对索引字段加的锁表级锁是针对非索引字段加的锁。当我们执行 UPDATEDELETE 语句时,如果 WHERE条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表对表中的所有行记录进行加锁。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值