MySQL:索引与事物

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: MySQL:索引与事物

简单了解索引的底层数据结构


索引的概念:


索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现


索引就是为了加快查询速度;在之前学习数组的时候,我们就是通过下标直接去查找到该位置的数据,同时我们也可以称之为索引。


索引存在的意义:


索引就是通过特殊的数据结构将数据组织在一起,这样查询时就不需要通过一行行遍历去找目标数据,此时的时间复杂度仍是 O(n) ,数据量少的时候没问题,但是一旦数据量太大,就会造成开销太大;我们这里的 O(n) 每一次都要读取硬盘,它的速率会比读取内存中的数据更慢;所以我们迫切的需要索引来减低访问磁盘的次数。


虽然索引增加了查询的速率,但是减低了 增上改 的效率,并且增加了更多的内存消耗。


索引的使用:


在 MySQL 代码中语法很简单:


创建索引:

create index 索引名 on 表名(字段名);

查看索引:

show index from 表名;

删除索引:

drop index 索引名 on 表名;


要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:

  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 索引会占用额外的磁盘空间。


当面对数据量大时去创建一个索引,系统为了创建这个索引而消耗过多的资源,导致机器无法正常工作;所以,索引在实际开发中并不会频繁使用。

对于索引的使用不是我们想要讨论的课题,我们学习索引更主要的是想了解索引底层的数据结构。


索引实现的数据结构


我们知道索引主要是增加查询效率的,我们之前学过两个主要用于查询的数据结构。

一个是二叉搜索树,一个是哈希表

那么索引是什么呢?

先来知道为什么二叉搜索数和哈希表不能用来创建索引:


  1. 二叉搜索树:二叉搜索树在极端情况(单分支)下树的高度非常的高,那么此时的查询速率就非常低效
  2. 哈希表:哈希表的实现原理是计算哈希值用来存放数据,而对于相邻的数据之前是无法比较的


那么我们在二叉搜索树的基础上就提出了B树


而B+ 树又是建立在B树的基础上,B树又叫 B - 树(不是B减树,是B 杠 树),是为索引量身定制的数据结构。

我们来简单认识一下B树和B+树。


B树


B树是棵N叉搜索树,每个节点具有多个key值,如图:


54a01f3fb29b4981a6ae141438e2b308.png

有 n 个 key 就将其分为 n + 1 个子节点,每个分组如下图:



90dd1f11b87445ba874de8b6b48ed292.png


当节点中的子树多,节点上保存的key就多,意味着同样key的个数的前提下B树的高度要远低于二叉搜索树;

树的高度越高,进行查询的时候,磁盘访问次数就越多!!!


B+ 树


B+ 又在B树的基础上作出改进( 树也是个N叉搜索树):

画图演示:


fffe508a2e534a9bb83c0b4cb02974b7.png

这样同样一棵树我们却只分为了 3 个域:


e64a5d3074b04c1faa43c9bb327916f4.png

 我们划分出的三个域不仅存了规定的值,并且还保留了关键的 key 。

这里的 50 是整个树中最大的值,该树中不可能出现大于50 的值。

我们再划分一次:


4410169f23ae4e9488edd051838fc54a.png

划分结束后类似于链表一样将其链接起来,这样整棵树的叶子节点包含了所有的数据,所有非叶子节点的 key 都出现在了叶子节点中。


这种‘链表’就是mysql组织数据的形式,当你看到一张表的时候,

实际上这个表不一定就是按照‘表格’这样的数据结构在硬盘上组织的,也有可以是按照这种书的结构组织的;(具体是那种哪种结构,取决于你表中的索引,以及数据库使用了哪种存储引擎)


树的特点


  1. 每个节点可以存在 n 个 key ,n 个 key 划分出 n 个子节点(B树的特点是划分出 n + 1 个子节点)。
  2. 每个 key 都会出现在叶子节点中,同时也是叶子节点中的最大值。
  3. B+ 树的叶子节点是首尾相连的,类似于一个链表
  4. 由于叶子节点是个完整的数据集合,只在叶子节点中存储数据表中每一行的数据,而非叶子节点只存 key 本身即可。



具体解释以下 第四点:


9281828a3ac3404f808e2fbbbd3207fe.png

我们设 id 为索引,那我们存储的值就是 id,在存数据时,不会将整个集合中的数据都存入,只存入一个id,其余的仍然保存在硬盘中,有需要的时候在去硬盘中取;为什么要怎么设计呢?因为内存空间是有序的:


569bec9994c84c7b810d4f1db6e63f64.png



B+ 树的优势


  1. 每个节点存储多个 key ,最终会使树相对较矮,这样在查询的时候就减少了IO(输入输出)访问次数(这里IO特指的是硬盘的访问)
  2. 最后所有的查询都会落到叶子节点上,这样无论查询多少次都可以保证查询效率是同样的,保证了稳定性;(稳定性对于程序员对这个树的评估更加准确)
  3. B+ 树的所有叶子节点构成链表,因此方便了进行范围查询(比如查询学生 id 在27 ~ 36之前的就非常快 )
  4. 由于数据都存在叶子节点上,非叶子节点只存在key,导致非叶子节点所占的内存是非常小的,这些非叶子节点就可以在内存缓存或者是内存换中的一部分,这样就进一步减少了IO访问!


至于B 树和B+ 树的代码就放在数据结构进阶的部分再继续!!!


事物


事物的概念


事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。

在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。


为什么要有事物这个概念


在很多年前,那个时候还没有微信转账,主要是靠银行卡之间进行转账,有时候会发生很多问题,比如:转账以后,另一方没有收到!!!


又比如,现在网传,台湾那边充话费需要半个小时才能到账!


有了事物,我们这一组操作,要么一起成功,要么一起失败。大大的提高了效率;

事物存在的意义就是将多个sql语句打成一个包,要么包内全部执行成功,要么包内全部执行不成功,不存在中间状态!


事物的使用


sql执行过程:


  1. 开启事务:start transaction;
  2. 执行多条SQL语句
  3. 回滚或提交:rollback/commit;

说明:rollback即是全部失败,commit即是全部成功。

举例 :

jerry 的账户原来有10000元,而tom 只有5000元,jerry 给 tom 转账 1000后的结果:


5de841af4b0949b4a84152ab89072c81.png


如果执行失败,并非是没有执行,而是执行以后将数据恢复未执行之前的状态,这个恢复的过程称之为 " 回滚 " (rollback)

例如上面这个例子,再jerry 转账过后系统崩了,但是钱却扣了;在下次重新启动系统后,就会把钱加回来!


进行回滚的时候咋知道恢复成什么样子呢?数据库中有个专门来记录事物的日志。

因此,使用事物的时候,执行sql语句开销是非常大的。

事物使用起来非常简单,但是理解起来有些难!


事物的四大特性

数据库的事物有四大关键特性(这也是面试中经常问的【八股文】)


  1. 原子性(事务中的每个sql语句都是最小的,不可再分的)
  2. 一致性(事物执行前后都是靠谱的)
  3. 持久性(事物执行的内容是存在硬盘上的,即使机器重启也不会丢失,因此数据是可持久的)
  4. 隔离性(为了解决“并发”执行事物,引起的问题)


隔离性这里重点讲解以下:

先来讲讲啥叫并发:

并发就是一个服务器为多个客户端提供服务;

如果并发是操作不同的数据,那么并发并不会造成影响,但是它并非都是操作不同数据,存在操作同一数据的情况。

例如上面的案例,假设多个用户对一个账号进行转账操作,那就会把数据搞乱。

事物的隔离性就体现在即使是并发事物操作也不会引发问题!

既然聊到并发,那就来聊聊并发可能引起的问题


并发可能引起的问题


脏读问题


什么叫脏读?

举个贴切的例子:

有一场考试中,隔壁的想抄我的答案,我故意给他看,但是后面我又将答案给改了,那么他看到的数据就是一个 “脏数据”。脏也就是无效的意思。

那么这么解决脏读的问题呢?

很简单,我们在写数据的时候给它进行加锁,mysql引入一个“写操作加锁” 机制。加锁是会提高耗能的,同时降低了效率,也增加了隔离性。

也就是说我考试的时候不给隔壁的人看。


不可重复读

举例:


还是那一场考试,我们约定好,我写完了给他抄,不故意坑他;在我第一次写完以后(version 1)给他抄了,在抄的过程中我发现自己写错了已一道题,我就又改了(version 2)这个时候他读着读着发现数据不一样了。

这个问题就是不可重复读。


事物1 提交了数据,事物2 开始读取,事物3 又去更新了数据,此时意味着事物在多次读取数据的结果是不一样的(预期应该是一样的)这就是不可重复读。

解决方法呢也是和上面一样加锁,此时给事物 “ 读 ” 加锁   此时又进一步增加了耗能的,同时降低了效率,也进一步增加了隔离性。


幻读


说明:事物A 读取了一次   事物B  对数据进行新增或者删除并提交事物  导致读取数据列表数据多了;此时就叫做幻读。


数据库使用  “ 串行化 ”  的方式来解决此类问题,并且彻底放弃并发处理事务,改用串行的方式一行行处理事物;此时的并发程度是最低的,效率也就最低,但是隔离性确是最高的。

针对上述问题又提出了事物的隔离级别


事物的隔离级别


83f4e7fd86b4402cbbc60e19d5239425.png



选用哪种级别,这时mysql内置的机制,可以通过修改mysql配置文件,来设置mysql工作环境。

具体如何使用 以及其代码在后面会写道。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3天前
|
SQL 存储 关系型数据库
mysql加索引真的会锁表吗?揭秘背后的技术细节与规避策略
【8月更文挑战第16天】在数据库管理中,添加索引能大幅提升查询效率。MySQL执行此操作时的锁定行为常引起关注。文章详细解析MySQL中索引添加时的锁定机制及其原理。不同存储引擎及SQL语句影响锁定策略:MyISAM需全表锁定;InnoDB提供更灵活选项,如使用`ALTER TABLE... LOCK=NONE`可在加索引时允许读写访问,尽管可能延长索引构建时间。自MySQL 5.6起,在线DDL技术可进一步减少锁定时间,通过`ALGORITHM=INPLACE`和`LOCK=NONE`实现近乎无锁的表结构变更。合理配置这些选项有助于最小化对业务的影响并保持数据库高效运行。
14 4
|
3天前
|
SQL JavaScript 关系型数据库
Mysql索引不当引发死锁问题
本文通过真实案例解析了MySQL在高并发环境下出现死锁的问题。数据库表`t_award`包含多个索引,但在执行特定SQL语句时遭遇索引失效,导致更新操作变慢并引发死锁。分析发现,联合索引`(pool_id, identifier, status, is_redeemed)`因`identifier`允许为空值而导致索引部分失效。此外,`pool_id`上的普通索引产生的间隙锁在高并发下加剧了死锁风险。为解决此问题,文中提出了调整索引顺序至`(pool_id, status, is_redeemed, identifier)`等方案来优化索引使用,进而减轻死锁现象。
|
6天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
19天前
|
存储 SQL 关系型数据库
(六)MySQL索引原理篇:深入数据库底层揭开索引机制的神秘面纱!
《索引原理篇》它现在终于来了!但对于索引原理及底层实现,相信大家多多少少都有了解过,毕竟这也是面试过程中出现次数较为频繁的一个技术点。在本文中就来一窥`MySQL`索引底层的神秘面纱!
|
19天前
|
SQL 存储 关系型数据库
(五)MySQL索引应用篇:建立索引的正确姿势与使用索引的最佳指南!
在本篇中,则重点讲解索引应用相关的方式方法,例如各索引优劣分析、建立索引的原则、使用索引的指南以及索引失效与索引优化等内容。
|
24天前
|
SQL 缓存 关系型数据库
MySQL 查询索引失效及如何进行索引优化
MySQL 查询索引失效及如何进行索引优化
60 1
|
26天前
|
SQL 缓存 关系型数据库
面试题MySQL问题之实现覆盖索引如何解决
面试题MySQL问题之实现覆盖索引如何解决
30 1
|
26天前
|
存储 SQL 索引
面试题MySQL问题之使用SQL语句创建一个索引如何解决
面试题MySQL问题之使用SQL语句创建一个索引如何解决
32 1
|
13天前
|
缓存 关系型数据库 MySQL
MySQL调优秘籍曝光!从索引到事务,全方位解锁高可用秘诀,让你的数据库性能飞起来!
【8月更文挑战第6天】MySQL是顶级关系型数据库之一,其性能直接影响应用的高可用性与用户体验。本文聚焦MySQL的高性能调优,从索引设计到事务管理,逐一解析。介绍如何构建高效索引,如联合索引`CREATE INDEX idx_order_customer ON orders(order_id, customer_id);`,以及索引覆盖查询等技术。
39 0
|
19天前
|
存储 SQL 关系型数据库
(四)MySQL之索引初识篇:索引机制、索引分类、索引使用与管理综述
本篇中就对MySQL的索引机制有了全面认知,从索引的由来,到索引概述、索引管理、索引分类、唯一/全文/联合/空间索引的创建与使用等内容,进行了全面概述。