MySQL索引事务

目录

  • 索引
    • 概念
    • 优缺点
    • 使用场景
    • 使用
      • 查看索引
      • 创建索引
      • 删除索引
    • 索引背后的数据结构
    • 总结
  • 事务
    • 概念
    • 原子性
    • 事务的基本特征
      • 原子性
      • 一致性
      • 持久性
      • 隔离性

索引

概念

1.索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。
2.当从数据库中进行查找的时候,例如按照一定的条件来查找,查找可以遍历表,但是遍历操作,比较低效。就需要想尽办法的避免遍历,可以通过一些特殊的数据结构,来表示一些记录的特征,通过这些特征来减少比较次数,加快比较的效率。
索引主要的意义就是进行查找,要提高查找的效率,但是查找的效率是提高了,但同时会付出代价。

以一本书为例
1.书的目录是费纸的,数据库的索引,也需要消耗一定的额外存储空间,数据量越大,索引消耗的额外空间剧越多。
2.书的目录确定了,后序每次对书的内容进行调整,都可能会影响目录的准确性,就需要重新调整目录。数据库的索引也一样,进行增删改的时候,往往也需要同步调整索引的结构。

优缺点

索引带来的好处,提高了查找的速度
索引带来的坏处,占用了更多的空间,拖慢了增删改的速度。

既然它的缺点比优点更多,那为什么还要用它呢???
索引是一个很常用的东西。实际需求场景中,查找操作往往是最高频的操作。
例如像老师布置作业一样,每节课都要布置作业,每天都要进行查询操作,但是如果某个同学反馈某个作业不合适,就需要进行增删改,可能这些操作几周或一个月才操作一次。

使用场景

  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 索引会占用额外磁盘空间。
    满足以上条件时,考虑对表中的这些字段创建索引,以提高询效率。反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。

使用

查看索引

show index from 表名;
在这里插入图片描述
查看student表的时候,发现里面已经自带了一个索引,这个自带的索引,就是primary这个主键约束带来的。

查询的时候,如果查询条件指定了根据主键查询,这个时候查询速度就会非常快。

unique 也带索引

创建索引

create index 索引名 on 表名(列名);
MySQL索引事务_第1张图片

创建索引是非常低效的,尤其是当表里有很多数据的时候。
注:后期针对线上的数据库,如果这个数据库没有索引,不要贸然创建索引。

删除索引

drop index 索引名 on 表名;
MySQL索引事务_第2张图片

删除索引操作和创建同理,都是非常低效的事。
在创建表的时候,就应该把索引规划好。

索引背后的数据结构

索引背后的数据结构要能够加快查找的速度。

此处说的查找,是“按照值”查找,不是按照“下标查找”。
扩展:为什么顺序表按照下标的访问速度快???
顺序表是在连续内存空间上的,内存支持随机访问操作。

二叉树不适合作为索引:当元素多的时候,高度就高了,高度对应着比较次数,对于数据库来说,每次比较都意味着磁盘IO.
哈希表也不适合。虽然哈希表的查找速度很快O(1),但哈希表只能很对“相等”进行判定,不能对“”大于小于”以及范围查找进行判定。

最适合做索引的,还是树形结构,如果使用“多叉搜索树”,高度自然就下降了。
在数据结构中,这样的树称为 B+ 树(这个是数据库索引中最常见的数据结构)。

要了解B+树,先来看看B树
MySQL索引事务_第3张图片
MySQL索引事务_第4张图片

总结

1.索引是干什么的
2.索引的适用场景,付出的代价
3.索引背后的数据结构

事务

概念

事务诞生的目的就是为了把若干个独立的操作给打包成一个整体。

举个例子
比如说,四十大盗把从阿里巴巴的账户上偷盗了2000元

– 阿里巴巴账户减少2000
update accout set money=money-2000 where name = ‘阿里巴巴’;
– 四十大盗账户增加2000
update accout set money=money+2000 where name = ‘四十大盗’;
假如在执行以上第一句SQL时,出现网络错误,或是数据库挂掉了,阿里巴巴的账户会减少2000,但是四十大盗的账户上就没有了增加的金额。
解决方案:使用事务来控制,保证以上两句SQL要么全部执行成功,要么全部执行失败,不存在只执行了第一步,不执行第二步的中间状态。

原子性

1.在SQL中,有的复杂的任务需要多个SQL来执行,有的时候,也同样需要打包在一起,前一个SQL是为了给后一个SQL提供支持,如果后一个SQL不执行了或者执行出错了,前一个SQL也就失去意义了。

这就体现了事务的原子性:要么全都执行完,要么一个都不执行,任务不可以在被细分了。
比如A给B转账500元,在转账的过程中,考虑一个极端情况,执行完第一个SQL之后,在执行第二个SQL之前,数据库崩了/程序崩了。显然这种中间状态是不科学的。(事务的原子性就能避免这种中间状态)

2.事务的原子性是怎样保证的呢?
原子性:全都执行/一个都不执行。
在执行第二个SQL之前,我们无法预知这次执行能失败,所以这个时候,还是的先执行第一个SQL,执行完了在执行第二个SQL。
此处的一个都不执行,并不是真正的一个都不执行,该执行还是得执行。当执行失败之后,数据库会自动的执行一些“还原”行的工作(回滚 rollback),来消除前面SQL带来的影响,所以看起来就好像一个都没执行

数据库是如何知道该还原成哪个值的呢?
数据库会把执行的每个操作,给记录下来

那么既然都能还原,是不是就可以放心大胆的删库呢?
数据库要想记录之前的详细操作,要消耗大量的时间和空间
因此这个记录势必不会保存很久的
我们的数据库可能是经过了一年甚至更久的时间沉淀出来的数据,但记录可能只是记录了几天的。

事务的基本特征

原子性

要么全都执行完,要么一个都不执行

一致性

在事务执行之前和执行之后,数据库中的数据应该是合理合法的。
例如:在转账之后,不能出现账户为负数的情况。

持久性

数据一旦提交了之后,数据就持久化存储起来了(数据就写入硬盘了)

隔离性

1.隔离性描述的是事务并发执行的时候,产生的情况。

并发编程,是当前最主要的编程方式

当并发执行多个事务,尤其是这多个事务尝试修改/读取同一份数据,这个时候就容易出现一些问题。事务的隔离性,就是在解决这个问题。

2.并发执行事务可能会带来的问题

举例
当老师在写代码的时候,有个同学偷偷的看到了(比如:代码里有一个student类,有一些属性),但是后来,老师把代码修改了,所以这位同学看到的这个数据不是最终版本的数据,而是中间过程。

  • 脏读问题
    事务A对某个数据进行修改的时候,事务B去读取了这个数据,此时,事务B读到的很可能是一个“脏数据”(这个数据是一个临时结果,而不是最终结果)
    【出现脏读的问题,原因是事务和事务之间没有任何的隔离,加上一些约束限制,就可以有效避免脏读问题。】
    如何处理脏读?【给写操作加锁】
    在修改的过程中,别人不能读,等修改完之后,别人才能读。
    一旦加这个锁之后,意味着事务之间的隔离性提高了,并发性就降低了。
  • 不可重复读
    在一个事务中,包含了多次的读操作,这多次的读操作读出来的结果不一致。
    MySQL索引事务_第5张图片
    如何处理不可重复读【给读操作加锁】
    读的时候,不能修改代码。等同学读完时候,才能进行修改。
    通过给读操作也加锁,就解决了不可重复读的问题。
    此时,事务之间的并发性降低了,隔离性提高了。
    MySQL索引事务_第6张图片

但是在同学读代码的这个时间内,就一直在等待吗?

  • 幻读
    一个事务执行过程中进行多次查询,多次查询的结果集不一样(多一条或者少一条),这个操作也算是一种特殊的不可重复读。
    MySQL索引事务_第7张图片

如何解决幻读?
彻底串行化执行。

隔离性最高,并发程度最低,速度最慢。

综上:并发(快)和隔离(准)是不可兼得的。
可以根据实际需求来调整数据库的隔离级别,通过不同隔离级别,也就控制了事务之间的隔离性,也就控制了并发性。

3.MySQL中事务的隔离级别
(1)read uncommitted。 允许读取未提交的数据,并发程度最高,隔离性最低,会引入脏读+不可重复读+幻读问题。
(2) read committed。 只允许读取提交之后的数据,相当于写加锁,并发程度降低了一些,隔离性提高了一些,解决了脏读,会引入不可重复读+幻读问题。
(3)repeatable read。 相当于给读和写都加锁,并发程度又降低,隔离性又提高,解决脏读和不可重复读,会引入幻读问题。
(4)serializable。 串行化。并发程度最低(串性执行),隔离性最高,解决了脏读。不可重复读、幻读问题,但是执行效率最低。

可以通过my.ini这个配置文件,来设置当前的隔离级别。
后面要根据实际需求场景,来决定使用哪种隔离级别。

你可能感兴趣的:(mysql,数据库)