MySQL 为我们提供了行锁、表锁、页锁三种级此外锁,个中表锁开销小,加锁快;不会呈现死锁;锁定力度大,产生锁斗嘴概率高,并发度最低。行锁开销大,加锁慢;会呈现死锁;锁定粒度小,产生锁斗嘴的概率低,并发度高;页锁开销和加锁速率介于表锁和行锁之间;会呈现死锁;锁定粒度介于表锁和行锁之间,并发度一样平常。每个存储引擎都可以有本身的锁计策,譬喻 MyISAM 引擎仅支持表级锁,而 InnoDB 引擎除了支持表级锁外,也支持行级锁(默认)。
InnoDB 行锁是通过给索引上的索引项加锁来实现的,这一点 MySQL 与 Oracle 差异,后者是通过在数据块中对响应数据行加锁来实现的。InnoDB 这种行锁实现特点意味着:只有通过索引前提检索数据,InnoDB 才行使行级锁,不然,InnoDB 将行使表锁,同样地,当 for update 的记录不存在会导致锁住全表。当表有多个索引的时辰,差异的事宜可以行使差异的索引锁定差异的行,其它,岂论是行使主键索引、独一索引或平凡索引,InnoDB 城市行使行锁来对数据加锁。
InnoDB 的加锁进程较量伟大,将全部扫描到的记录都加锁,范畴查询会加间隙锁,然后加锁进程凭证两阶段锁 2PL 来实现,也就是先加锁,然后全部的锁在事物提交的时辰开释。加锁的计策会和数据库的断绝级别有关,在默认的可一再读的断绝级此外环境下,加锁的流程还会和查询前提中是否包括索引,是主键索引照旧平凡索引,是否是独一索引等有关。
譬如对付 select * from o_order where order_sn = '201912102322' for update; 这条 SQL 语句,在差异的索引环境下其加锁计策也纷歧致:

- order_sn 是主键索引,这种环境将在主键索引上的 order_sn = 201912102322 这笔记录上加排他锁。
- order_sn 是平凡索引,而且是独一索引,将会对平凡索引上对应的一笔记录加排他锁,对主键索引上对应的记录加排他锁。
- order_sn 是平凡索引,而且不是独一索引,将会对平凡索引上 order_sn = 201912102322 一条可能多笔记录加锁,而且对这些记录对应的主键索引上的记录加锁。这里除了加上行锁外,还会加上间隙锁,防备其他事宜插入 order_sn = 201912102322 的记录,然而假如是独一索引就不必要间隙锁,行锁就可以。
- order_sn 上没有索引,innoDB 将会在主键索引上全表扫描,这里并没有加表锁,而是将全部的记录城市加上行级排他锁,而现实上 innoDB 内部做了优化,当扫描到一行记录后发明不匹配就会把锁给开释,虽然这个违反了 2PL 原则在事宜提交的时辰开释。这里除了对记录举办加锁,还会对每两个记录之间的间隙加锁,以是最终将会生涯全部的间隙锁和 order_sn = 201912102322 的行锁。
- order_sn = 201912102322 这笔记录不存在的环境下,假如 order_sn 是主键索引,则会加一个间隙锁,而这个间隙是主键索引中 order_sn 小于 201912102322 的第一笔记录到大于 201912102322 的第一笔记录。试想一下假如不加间隙锁,假如其他事物插入了一条 order_sn = 201912102322 的记录,因为 select for update 是当前读,纵然上面谁人事物没有提交,假如在该事物中从头查询一次就会产生幻读。
- 假如没有索引,则对扫描到的全部记录和间隙都加锁,假如不匹配行锁将会开释只剩下间隙锁。回想一下上面讲的数据页的功效中又一个最大记录和最小记录,Infimum 和 Supremum Record,这两个记录在加间隙锁的时辰就会用到。
【编辑保举】
- DBA大牛MySQL优化心得,语句执行加快就是这么简朴!
- 达梦DM8新品宣布 国产数据库迎来新的里程碑
- 成也数据库 败也数据库 Oracle 怎样云渡劫?
- 6月数据库排行:PostgreSQL 和 MongoDB 分数有数降落
- MySQL导致CPU耗损过大,怎样优化
【责任编辑:庞桂玉 TEL:(010)68476606】
点赞 0 (编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|