数据库系列:MySQL InnoDB锁机制介绍
数据库系列:MySQL慢查询分析和性能优化
数据库系列:MySQL索引优化总结(综合版)
数据库系列:高并发下的数据字段变更
数据库系列:覆盖索引和规避回表
数据库系列:数据库高可用及无损扩容
数据库系列:使用高区分度索引列提升性能
数据库系列:前缀索引和索引长度的取舍
数据库系列:MySQL引擎MyISAM和InnoDB的比较
数据库系列:InnoDB下实现高并发控制
数据库系列:事务的4种隔离级别
数据库系列:RR和RC下,快照读的区别
1 背景
随着互联网的发展,高并发业务的盛行,MySQL InnoDB引擎的细粒度行锁,变成很核心的特性之一。
在并发高的情况下,如果使用不当,会导致严重的性能问题。比如细粒度行锁,是实现在索引记录上的,但如果没有命中索引,就回退化成表锁,那对性能是灾难的。
下面我们从索引角度出发, 介绍下MySQL InnoDB的锁机制。
2 InnoDB的索引回顾
Innodb中有2种索引:主键索引(也叫聚集索引 Clustered Index)、辅助索引(也叫非聚集索引 Secondary Index)。
主键索引: 每个表只有一个主键索引,b+树结构,叶子节点存储主键的值以及对应整条记录的数据,非叶子节点不存储记录的数据,只存储主键的值。
当表中未指定主键时,MySQL内部会自动给每条记录添加一个隐藏的rowid字段(默认4个字节)作为主键,用rowid构建聚集索引。聚集索引在MySQL中即主键索引。
辅助索引: 每个表可以有多个辅助索引,b+树结构,非聚集索引叶子节点存储字段(索引字段)的值以及对应记录主键的值,其他节点只存储字段的值(索引字段),这就是与聚集索引不同的地方。每个表可以有多个非聚集索引。
InnoDB的每一个表都会有聚集索引:
- 假设表定义了PK,则PK就是聚集索引
- 如果未定义PK,则第一个非空unique列即是聚集索引
- 如果没有PK也没有非空unique列,InnoDB会创建一个隐含的row_id作为聚集索引使用
下图更形象说明这两种索引的区别,这边假设了一个存储4行数据的表。Id为主键索引,Name作为辅助索引,图中清晰的体现了聚簇索引和非聚簇索引的差异。
表中有四条记录:
5, Gates, Microsoft
7, Bezos, Amazon
11, Jobs, Apple
14, Elison, Oracle
InnoDB数据检索过程
上面的表中有2个索引:id作为主键索引,name作为辅助索引。
如果需要查询id=14的数据,只需要在左边的主键索引中检索就可以了。
如果需要搜索name='Ellison'的数据,需要2步:
- 先在辅助索引中检索到name='Ellison'的数据,获取id为14
- 再到主键索引中检索id为14的记录
辅助索引这个查询过程在mysql中叫做回表,相对于主键索引多了第二步操作。
MyISAM数据检索过程
- 在索引中找到对应的关键字,获取关键字对应的记录的地址
- 通过记录的地址查找到对应的数据记录
对比发现:Innodb中最好是采用主键索引查询,这样只需要一次索引,如果使用辅助索引检索,涉及多一步的回表操作,比主键查询要耗时一些。
所以,InnoDB的普通索引,实际上会扫描两遍:
第1遍,由普通索引找到PK:检索到name='Ellison'的数据,获取id为14
第2遍,由PK找到行记录:即到主键索引中检索id为14的记录
对索引有兴趣的,可以参考作者的这几篇文章:
MySQL全面瓦解22:索引的介绍和原理分析
MySQL全面瓦解23:MySQL索引实现和使用
MySQL全面瓦解24:构建高性能索引(策略篇)
3 InnoDB 几种常见锁
★InnoDB默认的事务隔离级别为可重复读(Repeated Read, RR),我们当下的所有介绍都是基于这个隔离级别为前提的。
- 记录锁(Record Locks):锁定单一行记录,InnoDB 使用记录锁来实现行级锁,这样允许多个事务并发访问不同的行。
- 间隙锁(Gap Locks):InnoDB 的特性,用于锁定一个范围,但不包括实际的记录。这主要用于防止幻读(Phantom Reads)。
- 临键锁(Next-Key Locks):InnoDB 存储引擎的一种锁定机制,在执行查询语句时,根据查询条件所锁定的一个范围。这个范围中包含有间隙锁和记录锁。它的设计目的是为了解决幻读(Phantom Reads)。
3.1 记录锁(Record Locks)
记录锁,它封锁索引记录,例如:
select * from table where id=5 for update;
它会在id=1的索引记录上加锁,以阻止其他事务插入,更新,删除id=1的这一行。
需要说明的是:
select * from table where id=5;
则是快照读(SnapShot Read),它并不加锁,快照读可以参考作者这篇文章:数据库系列:RR和RC下,快照读的区别
3.2 间隙锁(Gap Locks)
间隙锁,它封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
延续上面的那个例子继续演示:
# 表结构
table (Id PK, Name , Company);
# 表中包含四条记录
5, Gates, Microsoft
7, Bezos, Amazon
11, Jobs, Apple
14, Elison, Oracle
执行SQL语句如下:
select * from table
where id between 7 and 13
for update;
这样的话,会封锁数据的区间,以防止其他事务插入id=8的记录。
假设没有间隙锁,则可能够插入成功,而之前的select事务,会发现检索的结果集莫名多了一条记录,即幻影数据。
所以间隙锁主要目的用于防止幻读(Phantom Reads),避免其他事务在间隔中插入数据,导致 『不可重复读』。
如果把事务的隔离级别降级为读提交(Read Committed, RC),对,就是互联网最常用的隔离级别,间隙锁则会自动失效。
3.3 临键锁(Next-Key Locks)
临键锁(Next-Key Locks)是数据库管理系统InnoDB中的一种重要锁定机制。这种锁是查询时根据查询条件锁定的一个范围,这个范围包括间隙锁和记录锁,左开右闭,即不锁住左边界,但会锁住右边界。临键锁的主要设计目的是为了解决所谓的“幻读”问题。
# 左开右闭 示例
(-infinity, 1]
(1, 7]
(7, 9]
(9, +infinity]
依然沿用上面的例子,InnoDB引擎,RR隔离级别:
-- 创建一个示例表
CREATE TABLE users (
Id INT PRIMARY KEY,
Name VARCHAR(255) NOT NULL,
Company VARCHAR(255) NOT NULL,
);
-- 插入一些示例数据
INSERT INTO users (id, name, company) VALUES (1, 'Alice', 'ali');
INSERT INTO users (id, name, company) VALUES (2, 'Brand', 'tencent');
INSERT INTO users (id, name, company) VALUES (3, 'Charlie', 'baidu');
-- 开始一个事务,并使用临键锁查询数据
START TRANSACTION;
SELECT * FROM users WHERE id > 1 FOR UPDATE;
-- 在另一个事务中尝试插入新数据,将会被阻塞直到第一个事务释放锁
START TRANSACTION;
INSERT INTO users (id, name, age) VALUES (4, 'David', 30);
COMMIT;
-- 第一个事务提交后,第二个事务可以继续执行插入操作
COMMIT;
临键锁的主要目的,也是为了避免幻读(Phantom Read),在事务隔离级别为可重复读的情况下,InnoDB存储引擎默认使用临键锁。这种锁提供了一种有效的机制来保证在并发环境中数据的完整性和一致性。
如果把事务的隔离级别降级为RC,临键锁则也会失效。
4 总结
- InnoDB的索引与行记录存储在一起,MyISAM则是通过索引的地址查找到对应的数据记录,效率低一些
- InnoDB的聚集索引存储行记录,普通索引存储PK,所以普通索引要查询两次
- 记录锁锁定索引关联的具体记录
- 间隙锁锁定间隔,防止间隔中被其他事务插入
- 临键锁锁定索引记录+间隔,防止幻读
- elect...for update加锁的几种情况:
- 主键字段:加行锁。
- 唯一索引字段:加行锁。
- 普通索引字段:加行锁。
- 主键范围:加多个行锁。
- 普通字段:加表锁。
- 查询空数据:不加锁。
- 行锁与表锁的区别
- 如果事务1加了行锁,一直未释放锁,事务2操作相同记录,会一直等待直至超时。
- 如果事务1加了表锁,一直未释放锁,事务2无论操作哪一行记录,都会一直等待直到超时
数据库系列:MySQL InnoDB锁机制介绍的更多相关文章
- [转载] 数据库分析手记 —— InnoDB锁机制分析
作者:倪煜 InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工 ...
- MySQL InnoDB锁机制
概述: 锁机制在程序中是最常用的机制之一,当一个程序需要多线程并行访问同一资源时,为了避免一致性问题,通常采用锁机制来处理.在数据库的操作中也有相同的问题,当两个线程同时对一条数据进行操作,为了保证数 ...
- MySQL InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析
MySQL InnoDB支持三种行锁定方式: l 行锁(Record Lock):锁直接加在索引记录上面,锁住的是key. l 间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙 ...
- Mysql Innodb 锁机制
latch与lock latch 可以认为是应用程序中的锁,可以称为闩锁(轻量级的锁) 因为其要求锁定的时间必须要非常短,若持续时间长,则会导致应用性能非常差,在InnoDB存储引擎中,latch又可 ...
- MySQL- InnoDB锁机制
InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...
- MySQL的innoDB锁机制以及死锁处理
MySQL的nnoDB锁机制 InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,innodb正常的select ...
- Mysql锁机制介绍
Mysql锁机制介绍 一.概况MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking ...
- InnoDB锁机制分析
InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工作机制.通过 ...
- MySQL- 锁机制及MyISAM表锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许 多用户 共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
- mysql insert锁机制【转】
最近再找一些MySQL锁表原因,整理出来一部分sql语句会锁表的,方便查阅,整理的不是很全,都是工作中碰到的,会持续更新 笔者能力有限,如果有不正确的,或者不到位的地方,还请大家指出来,方便你我,方便 ...
随机推荐
- Prompt Playground 7月开发记录
Prompt Playground 2023年7月开发记录 上个月的时候,出于日常工作需求,做了一个简单的提示词调试工具 Prompt Playground. 这个工具的初衷是为了方便测试,所以没有做 ...
- Tibos.Devops项目介绍
诞生背景 随着微服务的普及,更多的企业选择迁移到云,传统的部署方式已经无法满足需求,市面上devops产品也应运而生,结合自己使用的经验,也制作了一款同类产品,并开源出来,与大家一起探讨学习 前置条件 ...
- GGTalk 开源即时通讯系统源码剖析之:客户端全局缓存及本地存储
继上篇<GGTalk 开源即时通讯系统源码剖析之:虚拟数据库>详细介绍了 GGTalk 内置的虚拟的数据库,无需部署真实数据库便能体验GGTalk的全部功能,虚拟数据库将极大地简化服务端的 ...
- Mybatis-plus SQL效率插件PerformanceInterceptor无效->替换为p6spy
使用mybatis-plus时,需要加入执行的sql分析 发现mybatis-plus中的PerformanceInterceptor无效了 查了信息发现 3.2.0 版本之后把这个功能可剔除了 可同 ...
- [TSG开发日志](一)软件基础框架
目录 前言 说明 框架 TSG_Framework 一.底层信号机制 TSG_Caller 二.参数类型声明 TSG_Params 三.设备类声明 TSG_Device 四.设备配置文件控制 TSG_ ...
- prometheus 监控实战篇
prometheus 监控 目录 prometheus 监控 1.上传tar包 2.解压到对应文件夹 3.配置开机自启动 4.配置Prometheus 5.black_exporter 监控网站状态 ...
- 解决Promise的多并发问题
提起控制并发,大家应该不陌生,我们可以先来看看多并发,再去聊聊为什么要去控制它 多并发一般是指多个异步操作同时进行,而运行的环境中资源是有限的,短时间内过多的并发,会对所运行的环境造成很大的压力,比如 ...
- Vue-入门vue,及第一个vue程序
一.初始Vue 什么是vue Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架.它基于标准 HTML.CSS 和 JavaScript 构建,并提 ...
- Centos7中防火墙打开3306端口(亲测)
开放3306端口 firewall-cmd --zone=public --add-port=3306/tcp --permanent 开启防火墙 systemctl start firewa ...
- 【Python进阶-PyQt5】00搭建PyQt5环境
1.创建独立开发虚拟环境 1.1虚拟环境简介 我们编写的程序,有时用到的Python库是不一样的,比如说开发桌面应用程序我们主要用到PyQt5相关的Python库.开发Web应用程序我们主要用到Dja ...