广告
返回顶部
首页 > 资讯 > 数据库 >MySQL中怎么实现索引和锁
  • 310
分享到

MySQL中怎么实现索引和锁

2024-04-02 19:04:59 310人浏览 安东尼
摘要

这篇文章将为大家详细讲解有关Mysql中怎么实现索引和锁,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。索引索引常见的几种类型索引常见的类型有哈希索引,有序数

这篇文章将为大家详细讲解有关Mysql中怎么实现索引,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

索引

索引常见的几种类型

索引常见的类型有哈希索引,有序数组索引,二叉树索引,跳表等等。本文主要探讨 mysql 的默认存储引擎 InnoDB 的索引结构。

InnoDB的索引结构

在InnoDB中是通过一种多路搜索树——B+树实现索引结构的。在B+树中是只有叶子结点会存储数据,而且所有叶子结点会形成一个链表。而在InnoDB中维护的是一个双向链表。

MySQL中怎么实现索引和锁

你可能会有一个疑问,为什么使用 B+树 而不使用二叉树或者B树?

首先,我们知道访问磁盘需要访问到指定块中,而访问指定块是需要 盘片旋转 和 磁臂移动 的,这是一个比较耗时的过程,如果增加树高那么就意味着你需要进行更多次的磁盘访问,所以会采用n叉树。

而使用B+树是因为如果使用B树在进行一个范围查找的时候每次都会进行重新检索,而在B+树中可以充分利用叶子结点的链表。

在建表的时候你可能会添加多个索引,而 InnDB 会为每个索引建立一个 B+树 进行存储索引。

比如这个时候我们建立了一个简单的测试

create table test(    id int primary key,    a int not null,    name varchar,    index(a)  )engine = InnoDB;

这个时候 InnDB 就会为我们建立两个 B+索引树

一个是 主键 的 聚簇索引,另一个是 普通索引 的 辅助索引,这里我直接贴上 Mysql浅谈(索引、锁) 这篇文章上面的贴图(因为我懒不想画图了。。。)

MySQL中怎么实现索引和锁

可以看到在辅助索引上面的叶子节点的值只是存了主键的值,而在主键的聚簇索引上的叶子节点才是存上了整条记录的值。

回表

所以这里就会引申出一个概念叫回表,比如这个时候我们进行一个查询操作

select name from test where a = 30;

我们知道因为条件 MySQL 是会走 a 的索引的,但是 a 索引上并没有存储 name 的值,此时我们就需要拿到相应 a 上的主键值,然后通过这个主键值去走 聚簇索引 最终拿到其中的name值,这个过程就叫回表。

我们来总结一下回表是什么?MySQL在辅助索引上找到对应的主键值并通过主键值在聚簇索引上查找所要的数据就叫回表。

索引维护

我们知道索引是需要占用空间的,索引虽能提升我们的查询速度但是也是不能滥用。

比如我们在用户表里用身份证号做主键,那么每个二级索引的叶子节点占用约20个字节,而如果用整型做主键,则只要4个字节,如果是长整型(bigint)则是8个字节。也就是说如果我用整型后面维护了4个g的索引列表,那么用身份证将会是20个g。

所以我们可以通过缩减索引的大小来减少索引所占空间。

当然B+树为了维护索引的有序性会在删除,插入的时候进行一些必要的维护(在InnoDB中删除会将节点标记为“可复用”以减少对结构的变动)。

比如在增加一个节点的时候可能会遇到数据页满了的情况,这个时候就需要做页的分裂,这是一个比较耗时的工作,而且页的分裂还会导致数据页的利用率变低,比如原来存放三个数据的数据页再次添加一个数据的时候需要做页分裂,这个时候就会将现有的四个数据分配到两个数据页中,这样就减少了数据页利用率。

覆盖索引

上面提到了 回表,而有时候我们查辅助索引的时候就已经满足了我们需要查的数据,这个时候 InnoDB 就会进行一个叫 覆盖索引 的操作来提升效率,减少回表。

比如这个时候我们进行一个 select 操作

select id from test where a = 1;

这个时候很明显我们走了 a 的索引直接能获取到 id 的值,这个时候就不需要进行回表,我们这个时候就使用了 覆盖索引。

简单来说 覆盖索引 就是当我们走辅助索引的时候能获取到我们所需要的数据的时候不需要再次进行回表操作的操作。

联合索引

这个时候我们新建一个学生表

CREATE TABLE `stu` (    `id` int(11) NOT NULL,    `class` int(11) DEFAULT NULL,    `name` varchar(255) DEFAULT NULL,    PRIMARY KEY (`id`),    KEY `class_name` (`class`,`name`) USING BTREE  ) ENGINE=InnoDB DEFAULT CHARSET=utf8

我们使用 class(班级号) 和 name 做一个 联合索引,你可能会问这个联合索引有什么用呢?我们可以结合着上面的 覆盖索引 去理解,比如这个时候我们有一个需求,我们需要通过班级号去找对应的学生姓名 。

select name from stu where class = 102;

这个时候我们就可以直接在 辅助索引 上查找到学生姓名而不需要再次回表。

总的来说,设计好索引,充分利用覆盖索引能很大提升检索速度。

最左前缀原则

这个是以 联合索引 作为基础的,是一种联合索引的匹配规则。

这个时候,我们将上面的需求稍微变动一下,这时我们有个学生迟到,但是他在门卫记录信息的时候只写了自己的名字张三而没有写班级,所以我们需要通过学生姓名去查找相应的班级号。

select class from stu where name = '张三';

这个时候我们就不会走我们的联合索引了,而是进行了全表扫描。

为什么?因为 最左匹配原则。我们可以画一张简单的图来理解一下。

我们可以看到整个索引设计就是这么设计的,所以我们需要查找的时候也需要遵循着这个规则,如果我们直接使用name,那么InnoDB是不知道我们需要干什么的。

当然最左匹配原则还有这些规则

  •  全值匹配的时候优化器会改变顺序,也就是说你全值匹配时的顺序和原先的联合索引顺序不一致没有关系,优化器会帮你调好。

  •  索引匹配从最左边的地方开始,如果没有则会进行全表扫描,比如你设计了一个(a,b,c)的联合索引,然后你可以使用(a),(a,b),(a,b,c) 而你使用 (b),(b,c),(c)就用不到索引了。

  •  遇到范围匹配会取消索引。比如这个时候你进行一个这样的 select 操作 

select * from stu where class > 100 and name = '张三';

这个时候 InnoDB 就会放弃索引而进行全表扫描,因为这个时候 InnoDB 会不知道怎么进行遍历索引,所以进行全表扫描。

索引下推

我给你挖了个坑。刚刚的操作在 MySQL5.6 版本以前是需要进行回表的,但是5.6之后的版本做了一个叫 索引下推 的优化。

select * from stu where class > 100 and name = '张三';

如何优化的呢?因为刚刚的最左匹配原则我们放弃了索引,后面我们紧接着会通过回表进行判断 name,这个时候我们所要做的操作应该是这样的

MySQL中怎么实现索引和锁

但是有了索引下推之后就变成这样了,此时 "李四" 和 "小明" 这两个不会再进行回表。

MySQL中怎么实现索引和锁

因为这里匹配了后面的name = 张三,也就是说,如果最左匹配原则因为范围查询终止了,InnoDB还是会索引下推来优化性能。

一些实践

哪些情况需要创建索引?

  •  频繁作为查询条件的字段应创建索引。

  •  多表关联查询的时候,关联字段应该创建索引。

  •  查询中的排序字段,应该创建索引。

  •  统计或者分组字段需要创建索引。

哪些情况不需要创建索引

  • 表记录少。

  •  经常增删改查的表。

  •  频繁更新的字段。

  •  where 条件使用不高的字段。

  •  字段很大的时候。

其他

  •  尽量选择区分度高的列作为索引。

  •  不要对索引进行一些函数操作,还应注意隐式的类型转换和字符编码转换。

  •  尽可能的扩展索引,不要新建立索引。比如表中已经有了a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

  •  多考虑覆盖索引,索引下推,最左匹配。

全局锁

MySQL提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。

一般会在进行 全库逻辑备份 的时候使用,这样就能确保 其他线程不能对该数据库做更新操作。

mvcC 中提供了获取 一致性视图 的操作使得备份变得非常简单,如果想了解 MVCC 可以参考

https://juejin.im/post/5da8493ae51d4524b25add55

表锁

MDL(Meta Data Lock)元数据锁

MDL锁用来保证只有一个线程能对该表进行表结构更改。

怎么说呢?MDL分为 MDL写锁 和 MDL读锁,加锁规则是这样的

  •  当线程对一个表进行 CRUD 操作的时候会加 MDL读锁

  •  当线程对一个表进行 表结构更改 操作的时候会加 MDL写锁

  •  写锁和读锁,写锁和写锁互斥,读锁之间不互斥

lock tables xxx read/write;

这是给一个表设置读锁和写锁的命令,如果在某个线程A中执行lock tables t1 read, t2 write; 这个语句,则其他线程写t1、读写t2的语句都会被阻塞。同时,线程A在执行unlock tables之前,也只能执行读t1、读写t2的操作。连写t1都不允许,自然也不能访问其他表。

这种表锁是一种处理并发的方式,但是在InnoDB中常用的是行锁。

行锁

我们知道在5.5版本以前 MySQL 的默认存储引擎是 MyISAM,而 MyISAM 和 InnoDB 最大的区别就是两个

  •  事务

  •  行锁

其中行锁是我们今天的主题,如果不了解事务可以去补习一下。

其实行锁就是两个锁,你可以理解为 写锁(排他锁 X锁)和读锁(共享锁 S锁)

  •  共享锁(S锁):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。也叫做读锁:读锁是共享的,多个客户可以同时读取同一个资源,但不允许其他客户修改。

  •  排他锁(X锁):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。也叫做写锁:写锁是排他的,写锁会阻塞其他的写锁和读锁。

而行锁还会引起一个一个很头疼的问题,那就是死锁。

如果事务A对行100加了写锁,事务B对行101加了写锁,此时事务A想要修改行101而事务B又想修改行100,这样占有且等待就导致了死锁问题,而面对死锁问题就只有检测和预防了。

next-key锁

MVCC 和行锁是无法解决 幻读 问题的,这个时候 InnoDB 使用了 一个叫 GAP锁(间隙锁) 的东西,它配合 行锁 形成了 next-key锁,解决了幻读的问题。

但是因为它的加锁规则,又导致了扩大了一些加锁范围从而减少数据库并发能力。具体的加锁规则如下:

  •  加锁的基本单位是next-key lock 就是行锁和GAP锁结合。

  •  查找过程中访问到的对象就会加锁。

  •  索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁。

  •  索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁。

  •  唯一索引上的范围查询会访问到不满足条件的第一个值为止。

关于MySQL中怎么实现索引和锁就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: MySQL中怎么实现索引和锁

本文链接: https://www.lsjlt.com/news/58424.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL中怎么实现索引和锁
    这篇文章将为大家详细讲解有关MySQL中怎么实现索引和锁,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。索引索引常见的几种类型索引常见的类型有哈希索引,有序数...
    99+
    2022-10-18
  • mysql中怎么实现重复索引与冗余索引
    这篇文章将为大家详细讲解有关mysql中怎么实现重复索引与冗余索引,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。重复索引:表示一个列或者顺序相同的几个列上建...
    99+
    2022-10-18
  • MySQL中怎么实现索引优化
    MySQL中怎么实现索引优化,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。建表// 建表  CREATE&nbs...
    99+
    2022-10-18
  • MySQL索引怎么实现分页探索
    这篇文章主要讲解了“MySQL索引怎么实现分页探索”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL索引怎么实现分页探索”吧!MySQL索引优化之分页探索表结构CREATE ...
    99+
    2023-06-21
  • MySQL中怎么实现高性能索引
    本篇文章为大家展示了MySQL中怎么实现高性能索引,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。什么是索引索引又可以称为键(key)是存储引擎用于快速找到记录的一种...
    99+
    2022-10-18
  • 怎么在MySQL中实现全文索引
    这期内容当中小编将会给大家带来有关怎么在MySQL中实现全文索引,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。使用用MATCH() ... AGAINST 方式来进行搜索...
    99+
    2022-10-18
  • MySQL中怎么实现一个搜索引擎
    本篇文章为大家展示了MySQL中怎么实现一个搜索引擎,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言 只有Innodb和myisam存储引擎能用全文索引...
    99+
    2022-10-18
  • mysql中怎么实现索引最左原则
    这期内容当中小编将会给大家带来有关mysql中怎么实现索引最左原则,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。建表CREATE TABLE `use...
    99+
    2022-10-18
  • MySQL中怎么实现全局锁和表锁
    今天就跟大家聊聊有关MySQL中怎么实现全局锁和表锁,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. 全局锁全局锁就是对整个数据库实例加锁。MyS...
    99+
    2022-10-18
  • sql中怎么实现聚集索引和非聚集索引
    这期内容当中小编将会给大家带来有关sql中怎么实现聚集索引和非聚集索引,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。聚集索引   一种索引,该索引中键值的逻辑顺序决定了表...
    99+
    2022-10-18
  • sqlserver中怎么实现聚集索引和非聚集索引
    这篇文章将为大家详细讲解有关sqlserver中怎么实现聚集索引和非聚集索引,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。create database m...
    99+
    2022-10-18
  • MySQL主键索引和非主键索引的实现
    目录主键索引(Primary Key Index):非主键索引(Secondary Index):在mysql中,主键索引和非主键索引有不同的作用和特点: 主键索引(Primary Key Index): 主键索引是一种...
    99+
    2023-10-27
    MySQL 主键索引 MySQL 非主键索引
  • 怎么在mysql中实现一个联合索引
    这篇文章将为大家详细讲解有关怎么在mysql中实现一个联合索引,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。联合索引联合索引的定义为(MySQL):ALTER TABLE ...
    99+
    2023-06-14
  • MySQL聚簇索引和非聚簇索引怎么用
    小编给大家分享一下MySQL聚簇索引和非聚簇索引怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! 索引分为聚簇索引和非聚簇...
    99+
    2022-10-18
  • MySQL中怎么创建和删除索引
    MySQL中怎么创建和删除索引,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.索引作用   在索引列上,除了上面提到...
    99+
    2022-10-18
  • mysql中聚集索引、辅助索引、覆盖索引、联合索引怎么用
    这篇文章主要介绍了mysql中聚集索引、辅助索引、覆盖索引、联合索引怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。聚集索引(Clustered Index)聚集索引就是...
    99+
    2023-06-29
  • mysql中怎么查看索引
    本篇文章为大家展示了mysql中怎么查看索引,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。SHOW INDEX FROM tbl_name [FROM db_nam...
    99+
    2022-10-18
  • MySQL中怎么使用索引
    今天就跟大家聊聊有关MySQL中怎么使用索引,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。  MySQL何时使用索引  对一个键码使用>,&g...
    99+
    2022-10-18
  • MySQL中怎么实现死锁
    这篇文章将为大家详细讲解有关MySQL中怎么实现死锁,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1.了解锁等待与死锁出现锁等待或死锁的原因是访问数据库需要...
    99+
    2022-10-18
  • mysql中B+Tree索引和Hash索引有什么区别
    这篇文章主要为大家展示了“mysql中B+Tree索引和Hash索引有什么区别”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“mysql中B+Tree索引和Hash索引有什么区别”这篇文章吧。1、...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作