Mysql 索引 、事务、隔离级别

目录

索引(index)

1.为什么要有索引?

2.引入索引的代价

3.索引的操作

4.索引的使用场景

5.索引的底层原理

事务 (transaction)

事物的回滚是怎么做到的

事物的四大特性

并发执行事务带来的问题

隔离级别


索引(index)

索引是一种为了加快数据库查询(操作)速度而引入的一种手段,需要占用额外的磁盘空间,我们之前所学的主键,唯一键,外键都是自带了索引的。另外我们也可以自己手动为某个字段(列)设置索引。并且手动添加的可以删除索引,但是像主键这种自带索引的是无法删除索引的。一个表可以有多个索引。

1.为什么要有索引?

首先我们要了解数据库查询(select)操作具体是怎样执行的:

  1. 遍历整个表。
  2. 将每一行、每个记录带入查询条件,看条件是否成立。
  3. 条件成立,则保留这一行记录,不满足就跳过。

从上面的执行过程来看,查询操作的时间复杂度是O(n),如果这个表的数据量很大,遍历起来就会很费时间。并且数据库的数据都是存储在硬盘上的,读硬盘操作这个过程本身开销就大。

2.引入索引的代价

引入索引虽然能够提高查询速度,但同时也是有代价的:

  1. 会占用更多的磁盘空间。生成索引,是需要存储额外的数据结构以及数据的。
  2. 可能会降低插入、修改、删除数据的速度。
  3. 增加查询优化器的负担。

3.索引的操作

  • 1.查看索引  show index from 表名;

例如:show index from student;

  • 2.创建索引  create index 索引名 on 表名(列名);

例如:create index idx_student_name on student(name); //注意索引名的写法

其实创建索引操作,也是一个危险操作,特别是在你表已经创建好且表中数据量极大时,此时创建索引,会极容易把数据库服务器给卡住。一个有效的解决方法是:另外在弄一台机器,在这台机器上部署mysql服务器,并且创建一张同样的表,然后创建好索引,最后再将原服务器上的数据导入到新的mysql服务器上。导的过程中注意控制节奏。当所有数据都导入完毕,新的数据库就可以替代旧的数据库了。

  • 3.删除索引 drop index 索引名 on 表名;

例如:drop index idx_student_name on student; //注意索引名的写法

实际开发中,查询(读)的频率是高于修改(写)的频率的。所以引入索引还是非常有必要的。

4.索引的使用场景

  1. 一个表的主键,外键,唯一键都是自动创建了索引的,且不能删除。
  2. 一个表中的某个字段(数据列)经常查询,查询频率高并且添加、修改、删除的频率低时建立索引。
  3. 数据量大,磁盘空间大时,要考虑建立索引。数据量大建立索引是因为可以优化查询的速度。磁盘空间大建立索引是因为建立索引需要额外的空间存储。

索引是针对某一列,某个字段。只有对加索引的列进行条件查询的时候,查询速度才能被优化。即就是假如有一个学生表,字段有学生id,name等。只有学生id加了索引。那么where后条件查询是id的话才会优化查询速度。但若where后跟name则不会优化。

5.索引的底层原理

数据库索引用的是何种数据结构?

引入数据库的目的就是使查询操作更快,时间复杂度低。我们所知的在查询方面时间复杂度低的数据结构有哈希表,红黑树等。但是哈希表只能精确查询,并不能进行范围查询和模糊查询,因此并不适合作为索引的数据结构。而红黑树虽然既可以精确查询,又可以范围查询,还可以模糊匹配(但是%开头的这种模糊查询不支持),缺点是红黑树是一个二叉树,树的高度可能会很高,会导致IO操作频繁。

其实数据库索引操作使用的数据结构是 B+树 (即N叉搜索树)。

先说说B树:

本质上还是N叉搜索树,特点是每个节点里有多个key值,每个节点的子树个数由key的个数决定,若一个节点上保存有N个key就会划分出N+1个区间,N+1个子树。并且每个节点中key的个数也不是无限制的,达到一定的规模,就会触发节点的分裂。当删除元素达到一定的数目后,也会触发节点的合并。

N越大,树的高度就越低,读硬盘的次数就越少。由于每个节点中的所有key值都是存储在硬盘的一个区域中的,一次读硬盘操作就能读取出一个节点中的所有值。树的高度越低越好。

B+树是在B树的基础上做了一些改进,比如说范围查询更简单快速了。具体改进如下:

  1. B+树也是一个N叉搜索树,但其一个节点上若存在N个key,会划分成N个节点。
  2. 每个节点中的所有key值,都是按照从小到大排列的,最后一个key,就被认为是该节点下子树的最大值,就没有去划分区间。
  3. 父节点中的每个key值都会在子节点中出现(可能还会重复出现),所以在最下面的叶子结点这一层,就会包含整棵树的所有key值(全集)。 
  4. 在叶子结点这层,B+树用了链表这样的数据结构,把所有叶子结点串起来。对于范围查询操作来说更简单快速了。

B+树的优点(相对于B树,哈希表,红黑树而言)

  1. 是一个N叉搜索树,树的高度低,减少读硬盘的操作(IO操作)。
  2. 叶子结点之间使用了链表,非常适合范围查询。
  3. 所有查询最终都是要查询到叶子结点这一层的,每次查询的时间是稳定的。即就算头结点就是你要查询的值,但还是会一步步查询到叶子结点的,并且叶子结点是全集。
  4. 由于叶子结点是全集,为了节省空间,会把行数据只存储在叶子结点上,非叶子节点只存储一个用来排序的key值。这样非叶子节点就不会占太大空间,当进行查询的时候再把非叶子节点缓存到内存中 (即就是非叶子节点也在硬盘中存储,但当我们查询的时候,可以把这些叶子结点加载到内存中,后续比较这些非叶子节点就不用去硬盘中读取了,减少IO操作次数) 。这就是第三点为啥每次都要查询到叶子结点那一层了的一部分原因。 

问题来了,非叶子节点存储到内存中,内存会不够吗?

假设排序的key值用int型,就是4个字节。假设表中有一亿条数据,就是一亿个key值,一亿个key值就是4亿字节,4亿字节约等于400MB,对于现在的内存空间来说是足够的。

字节单位转换:千字节对应KB、百万字节对应MB、十亿字节对应GB 。

另外mysql索引实现也并不只是B+树这一种,还有一种存储引擎,比如Innodb,就是mysql最常用的存储引擎。


事务 (transaction)

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

假如做一件事,要么正确做完,要么"都不做",不能出现做一半的情况。都不做并不意味着都不做,在数据库中是指"回滚(rollback)"。

假如A给B转钱1000元,转钱是需要执行多条sql语句的,假如执行完第一句sql语句时,出现网络错误,或者是数据库挂掉了。A的账户会减少1000元,但是B的账户却没有多出1000元(因为第二条语sqi语句没有执行)。解决办法就是:使用事物来控制,保证以上两个sql语句要么全部执行成功,要全部执行失败。即就是事物的原子性。

事物的回滚是怎么做到的

使用日志的方式,记录事务中的关键操作(增删改查等操作),这种记录就是回滚的依据。

事物的四大特性

  1. 原子性。使用会滚的的方式
  2. 一致性。事务执行之前和之后,数据都不能出现离谱的情况。
  3. 持久性。事务作出的修改,都是在硬盘上持久保存的,重启服务器,数据依然存在。
  4. 隔离性。数据库并发执行多个事物时。

由于mysql数据库是一个客户端-服务器结构的程序。一个服务器经常会给多个客户端提供服务,很有可能会出现客户端1提交的事务执行了一半,客户端2提交的事务也来了。这时数据库就需要同时处理这两个事物,并发执行。如果事务之间穿行执行,即事物之间排队一个一个执行,效率就会非常低。所以事务并发执行是很有必要的。并发程度越高,执行的效率就越高。但是效率虽然高了,却也会出现一些"数据错误"的问题。比如:

并发执行事务带来的问题

1.脏读问题

例如事务A正在执行写数据操作的过程中,事务B读取这个数据。后续事务A又继续进行了修改(因为A还没执行完),这就会导致事务B读取到的数据不准确/过时/无效。也被称为脏数据。 

脏读解决方法:核心思路就是针对写操作加锁。写的时候不准读。写完才能读。并发性降低了,隔离性提高了,效率降低了,数据准确性提高了。  

上面虽然解决了脏读问题,但是只是约定了写的时候不能读,并没有约定读的时候不能写,就会造成不可重复度问题。

2.不可重复读问题

一个事物在内部多次读取到同一个数据却出现数据不同的情况。这是因为事务A在两次读取数据的期间,事务B对该数据进行了修改并提交了事务。

不可重复读解决方法:对读操作进行加锁。约定读的时候不能写。并发性降低了,隔离性进一步提高了,效率降低了,数据准确性也进一步提高了。  

3 .幻读问题

主要是结果集发生变化 。上面虽然解决了脏读和不可重复度问题。但是不可重复读约定的是事务A读a文件时,事务B不能写(修改)a文件,但是没规定事务B不能写b文件呀。此处说的问题不是说我读一个文件时,这个文件内容刷一下的变化了,而是我一次查询本来只有几个文件,结果一会又多出来或少了几个文件。主要指的是结果集的变化。即就是数据内容没变化,但是结果集变了。

幻读解决办法:引入串行化的方式,保证事务穿行执行,此时便完全没有并发了。此时隔离性是最高的,效率是最低的,数据是最准确的。 

综上所述,并发程度越高,隔离性越低,虽然效率高了,但带来的问题也越多。并发程度越低,隔离性越高,虽然效率低了,但是问题少。


隔离级别

对于注重效率还是注重数据正确不同的需求场景有不同的要求。mysql服务器也提供了"隔离级别",使我们针对不同的需求场景可以自行设置。具体是在mysql的配置文件中修改数据库的隔离级别,总共有四种隔离级别。 

隔离级别

就是在"数据正确"和"效率"之间做权衡。往往我们提升了效率,就会牺牲正确性;提升了正确性,就回牺牲效率。如果两个事物之间的影响越大,隔离性就越低;影响越小,隔离性就越高。

使用场景

充值、转账等一些与钱相关的场景,宁可不要效率,也要保证数据的准确性。

短视频、点赞、转发的数量等等这些场景下,对于准确性就不用要求太高。

四种隔离级别

  1. read uncommitted(读未提交)并发程度最高,速度最快,隔离性最低,准确性最低。
  2. read committed(读已提交)引入了写加锁。只能在写完之后再读。并发程度降低了,速度降低了;隔离性提高了,准确性提高了。
  3. repeatable read (可重复读) 引入了写加锁和读加锁,写的时候不能读,读的时候不能写。并发程度又进一步降低了,速度降低了;隔离性提高了,准确性提高了。mysql默认的级别。
  4. serialiazble(串行化)严格按照串行执行的方式,一个一个的执行事务。无并发,速度最低;隔离性最高,准确性最高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/334136.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenSource - 工具管理器easy-manager-tool

文章目录 功能说明运行配置环境配置启动docker部署 项目安全UI展示 Easy-Manager-Tool 打造软件行业首款集成工具,不管你是程序员,测试,运维等都可以使用该软件来提升自己的工作效率。 Easy-Manager-Tool 的诞生是为了解决软件行业众多参与者…

在 wsl-ubuntu 里通过 docker 启动 gpu-jupyter

在 wsl-ubuntu 里通过 docker 启动 gpu-jupyter 0. 背景1. 安装 docker-ce2. 安装 NVIDIA Container Toolkit3. 使用 nvidia-ctk 命令配置容器运行4. 通过 docker 运行 nvidia-smi5. 运行 gpu-jupyter6. 访问 gpu-jupyter7. 测试 gpu-jupyter 是否可以访问 cuda 0. 背景 今天突…

了解Vue中日历插件Fullcalendar

实现效果如下图: 月视图 周视图 日视图 官方文档地址:Vue Component - Docs | FullCalendar 1、安装与FullCalendar相关的依赖项 npm install --save fullcalendar/vue fullcalendar/core fullcalendar/daygrid fullcalendar/timegrid fullcalend…

485.最大连续1的个数

前言 这两天突然发现力扣上还是有我能写出来的题的,虽说都是简单级别的(以及一道中等的题),但是能写出来力扣真的太开心了,(大佬把我这段话当个玩笑就行了),于是乎,我觉…

class_10:this关键字

this关键字是指向调用对象的指针 #include <iostream> #include <iostream> using namespace std;class Car{ public://成员数据string brand; //品牌int year; //年限//构造函数名与类名相同Car(string brand,int year){cout<<"构造函数中&#…

自学C语言-4

第4章 运算符与表达式 了解了程序中常用的数据类型后&#xff0c;还应该懂得如何操作这些数据。因此&#xff0c;掌握C语言中各种运算符与表达式是必不可少的。本章致力于使读者了解表达式的概念&#xff0c;掌握运算符及相关表达式的使用方法&#xff0c;其中包括赋值运算符、…

ChatGPT给出的前端面试考点(Vue.js)

ChatGPT给出的前端面试考点&#xff08;Vue.js&#xff09; 答案 1. Vue.js是什么&#xff1f;它的主要特点是什么&#xff1f; Vue.js是一个渐进式JavaScript框架&#xff0c;用于构建用户界面。它的主要特点包括&#xff1a; 数据绑定&#xff1a;Vue.js使用双向数据绑定&…

【2015~2024】大牛直播SDK演化史

大牛直播SDK的由来 大牛直播SDK始于2015年&#xff0c;最初我们只是想做个低延迟的RTMP推拉流解决方案&#xff0c;用于移动单兵等毫秒级延迟的场景下&#xff0c;我们先是实现了Android平台RTMP直播推送模块&#xff0c;当我们用市面上可以找到的RTMP播放器测试时延的时候&am…

C++深入之虚函数、虚继承与带虚函数的多基派生问题

基础 在讲解带虚函数的多基派生问题时&#xff0c;我们要先弄清楚不带虚函数的多基派生存在什么样的问题&#xff0c;这样才好弄明白带虚函数的多基派生问题。 多基派生的二义性问题 一般来说&#xff0c;在派生类中对基类成员的访问应当具有唯一性&#xff0c;但在多基继承…

国考省考行测:语句排序2刷题

国考省考行测&#xff1a;语句排序2刷题 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和行测的重要知识点…

RabbitMQ 部署与配置[CentOS7]

# RabbitMQ,Erlang 版本包对应 https://rabbitmq.com/which-erlang.html#eol-seriescd /usr/local/src# Erlang下载 # https://github.com/rabbitmq/erlang-rpm/releases https://github.com/rabbitmq/erlang-rpm/releases/download/v23.3.4.5/erlang-23.3.4.5-1.el7.x86_64.rp…

鸿蒙原生应用/元服务开发-延迟任务说明(一)

一、功能介绍 应用退至后台后&#xff0c;需要执行实时性要求不高的任务&#xff0c;例如有网络时不定期主动获取邮件等&#xff0c;可以使用延迟任务。当应用满足设定条件&#xff08;包括网络类型、充电类型、存储状态、电池状态、定时状态等&#xff09;时&#xff0c;将任务…

STM32G4芯片SPI1 CLK管脚AF Mode自动变化为0的问题

1 问题描述 最近在调试SPI Slave程序&#xff0c;遇到一个很奇怪的问题&#xff1a;单步调试时SPI1 CLK管脚AF Mode自动变化为0&#xff1b;但是在管脚初始化时&#xff0c;已经将其配置为5了。 2 问题现象 通过视频可见&#xff1a; STM32G4芯片SPI1 CLK管脚AF Mode自动变化…

写点东西《什么是网络抓取?》

写点东西《什么是网络抓取&#xff1f;》 什么是网络抓取&#xff1f; 网络抓取合法吗&#xff1f; 什么是网络爬虫&#xff0c;它是如何工作的&#xff1f; 网络爬虫示例 网络抓取工具 结论 您是否曾经想同时比较多个网站上同一件商品的价格&#xff1f;或者自动提取您最喜欢的…

win系统环境搭建(十四)——Windows系统下使用docker安装mysql8和mysql5.7

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7 文章目录 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7MySQL81.新建文件夹2.创建…

实战之-Redis商户查询缓存

一、什么是缓存? 前言:什么是缓存? 就像自行车,越野车的避震器 举个例子:越野车,山地自行车,都拥有"避震器",防止车体加速后因惯性,在酷似"U"字母的地形上飞跃,硬着陆导致的损害,像个弹簧一样; 同样,实际开发中,系统也需要"避震器",防止过高…

Docker-nacos集群部署

nacos单机模式 先拉取一个mysql docker pull mysql:5.7 定义一个挂载目录 mkdir -p /mysql/{conf,data,script} 配置一个my.cnf放到conf目录下 开启mysql容器 privilegedtrue:使用该参数&#xff0c;container内的root拥有真正的root权限&#xff0c;否则&#xff0c;cont…

48-DOM节点,innerHTML,innerText,outerHTML,outerText,静态获取,单机click,cssText

1.DOM基础 Document Object Module,文档对象模型,window对象,document文档,都可以获取和操作 1)文档节点 2)属性节点(标签内的属性href,src) 3)文本节点(标签内的文字) 4)注释节点 5)元素节点(标签) 2.获取元素节点 2.1通过标签名获取getElementsByTagName() …

LeetCode、374. 猜数字大小【简单,二分】

文章目录 前言LeetCode、374. 猜数字大小【简单&#xff0c;二分】题目及类型思路及代码实现 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技…

RabbitMQ安装和使用

简介 RabbitMQ是一套开源&#xff08;MPL&#xff09;的消息队列服务软件&#xff0c;是由LShift提供的一个Advanced Message Queuing Protocol (AMQP) 的开源实现&#xff0c;由以高性能、健壮以及可伸缩性出名的Erlang写成。所有主要的编程语言均有与代理接口通讯的客户端库…