MySQL系列文章---初识MySQL中的锁

MySQL系列文章—初识MySQL中的锁



前言

MySQL中有很多种存储引擎,不同的存储引擎对应的不同的锁机制,如MyISAM和MEMORY存储引擎采用的是表级锁(Table-Level Locks);BDB存储引擎采用的是页面锁(Page-Level Locks),但也支持表级锁;InnoDB存储引擎既支持行级锁(Row-Level Locks),也支持表级锁,还有单列索引、Gap Locks(间隙锁)、Next-Key Locks锁。但默认情况下是采用行级锁。其中InnoDB和MyISAM是存储引擎中最常用的两种。


提示:以下是本篇文章正文内容,下面案例可供参考

一、按照锁的粒度划分

1.1 行锁 (Row-Level Locks)

简单的来说,行锁就是一锁锁一行或者多行记录,MySQL的行锁是基于索引加载的 ,所以行锁是要加在索引响应的行上,即命中索引。

行锁的优点:

  • 高并发时候锁冲突小
  • 事务失败,回滚代价小
  • 可以长时间锁一行

行锁的缺点:

  • 会出现死锁
  • 比表锁和页锁消耗内存更多,开销更大,请求更慢

代码示例,给指定的行加锁:

select * from A where id > 6 for update

1.1.1 记录锁 (Record Locks)

记录锁总是锁定索引记录,即使定义的表没有索引。对于这种情况, InnoDB创建一个隐藏的聚集索引并将该索引用于记录锁定。

1.1.2 间隙锁 (Gap Locks)

间隙锁是在索引记录之间的间隙上的锁,或在第一条索引记录之前或最后一条索引记录之后的间隙上的锁,不包括记录本身,可以防止同一个事物的两次当前读出现的幻读问题。间隙可能跨越单个索引值、多个索引值,甚至是空的。使用唯一索引锁定行以搜索唯一行的语句不需要间隙锁定。如果id没有索引或具有非唯一索引,则该语句会锁定前面的间隙。这里还值得注意的是,不同的事务可以在间隙上持有冲突的锁。例如,事务 A 可以在一个间隙上持有一个共享间隙锁(gap S-lock),而事务 B 在同一个间隙上持有一个排他性间隙锁(gap X-lock)。允许冲突间隙锁的原因是,如果从索引中清除记录,则必须合并不同事务在记录上持有的间隙锁。

1.1.3 临键锁 (Next-Key Locks)

临键锁是索引记录上的记录锁和索引记录之前的间隙上的间隙锁的组合。
InnoDB存储引擎中执行行级锁定的方式是,当它搜索或扫描表索引时,它会在它遇到的索引记录上设置共享或排他锁。因此,行级锁实际上是索引记录锁。索引记录上的 next-key 锁定也会影响该索引记录之前的“ gap ”。也就是说,next-key 锁是索引记录锁加上索引记录前面的间隙上的间隙锁。如果一个会话在索引中的记录R上具有共享或排他锁 ,则另一个会话不能在索引顺序记录R中之前的间隙中插入新的索引记录。默认情况下,InnoDB在 REPEATABLE READ事务隔离级别下运行。在这种情况下,InnoDB使用 next-key 锁进行搜索和索引扫描,这可以防止幻读。

1.1.4 插入意向锁 (Insert Intention Locks)

插入意向锁是一种由insert操作在行插入之前设置的间隙锁类型。这个锁表明了插入的意图,如果插入到同一个索引间隙中的多个事务没有插入到间隙中的相同位置,那么它们就不需要互相等待。假设有值为4和7的索引记录。尝试分别插入值为5和6的独立事务,在获得插入行的排他锁之前,每个事务使用插入意图锁锁定4和7之间的间隙,但不会相互阻塞,因为行不冲突。

1.2 表锁 (Table-Level Locks)

表级锁是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持。最常使用的 MyISAM 与 InnoDB 都支持表级锁定。表级锁定分为表共享读锁(Table Read Lock)与表独占写锁(Table Write Lock)。
MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写请求;MyISAM表的读和写操作之间,以及写和写操作之间是串行的

表锁的优点:

  • 开销小,加锁快
  • 不会出现死锁

表锁的缺点:
锁定粒度大,发生锁冲突的概率最高,并发度最低。

代码示例,直接给整个表加锁:

select * from A where niu = 'a' for update

1.3 页锁 (Page-Level Locks)

页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁,一次锁定相邻的一组记录,BDB存储引擎中支持页级锁。

页锁的特点:
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

二、锁级别分类

2.1 共享锁(Shared Locks)

共享 ( S) 锁允许持有该锁的事务读取一行 。
共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。

代码示例:

SELECTLOCK IN SHARE MODE;

2.2 排他锁(Exclusive Locks)

排他 ( X) 锁允许持有该锁的事务更新或删除一行 。
排他锁又称写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的锁。获取排他锁的事务可以对数据A进行更新或删除,其他事务不能再对A加任何锁,直到T 释放A上的锁。

代码示例:

SELECTFOR UPDATE;

2.3 意向锁 (Intention Locks)

意向锁是表级锁,它指示事务稍后对表中的行需要哪种类型的锁(共享或独占)。有两种类型的意图锁:

2.3.1 意向共享锁(Intention-Shared Locks)

表示事务打算在表中的各个行上设置共享锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。

2.3.2 意向排他锁(Intention-Exclusive Locks)

表示事务打算对表中的各个行设置排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IS锁。

2.4 基本锁和意向锁的兼容性

XIXSIS
X冲突冲突冲突冲突
IX冲突兼容冲突兼容
S冲突冲突兼容兼容
IS冲突兼容兼容兼容

注:
如果锁与现有锁兼容,则将锁授予请求事务,但如果与现有锁冲突则不会。事务等待直到释放冲突的现有锁。如果锁请求与现有锁冲突并且由于会导致死锁而无法授予 ,则会发生错误,MySQL会有报错信息(可以使用对应的存储引擎监视器,如 InnoDB 监视器 输出 SHOW ENGINE INNODB STATUS 命令查看信息)。


三 自增锁(AUTO-INC Locks)

AUTO-INC锁是一种特殊的表级锁,由插入到带有AUTO_INCREMENT列的表中的事务获取。在最简单的情况下,如果一个事务向表中插入值,那么任何其他事务都必须等待自己向表中插入值,以便由第一个事务插入的行接收到连续的主键值。

四 断言锁(Predicate Locks)

InnoDB支持包含空间数据的列的空间索引,为了处理涉及空间索引的操作的锁,临键锁不能很好地支持REPEATABLE READ或SERIALIZABLE事务隔离级别。多维数据中没有绝对的排序概念,因此不清楚哪个是临键。为了支持具有空间索引的表的隔离级别,InnoDB使用断言锁。空间索引包含最小边界矩形(MBR)值,因此InnoDB通过在用于查询的MBR值上设置一个断言锁来强制对索引进行一致的读取。其他事务不能插入或修改匹配查询条件的行。

总结

以上就是我对MySQL锁的一些简单理解

著作权归NoLongerConfused所有。商业转载请联系NoLongerConfused获得授权,非商业转载请注明出处。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NoLongerConfused

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值