【MySQL】索引与事务

目录

🌟 索引 

        ✍1. 什么是索引

        ✍2. 选择索引的数据结构是哪种?(面试常考)

        ✍3. 了解几个关于索引的概念

🌟 事务

        ✍1. 什么是事务

        ✍2. 事务的特性 (ACID)

        ✍3. 事务的隔离级别(重点掌握)


🌟 索引 

        ✍1. 什么是索引

        问题1:什么是索引?

        索引是为了提高查询效率而使用的一种数据结构是为了将数据组织起来。可以将索引理解为书的目录,通过索引可以快速找到想要查找的内容。

       问题2:为什么要使用索引?

       目的是为了提高查询效率。 如果没有索引,那么查找的时候就要遍历整个数据集,时间复杂度大大增加。数据库的索引是一个单独的文件,在保存索引的时候也需要空间。可以理解为这是一个典型的空间换时间的操作:因为创建索引也要占用一定的空间,而且在数据新增和删除时的开销也很大,因为不但要更新数据行,还要更新索引。因此索引一般创建在频繁查询的列上,且这个列中的重复值较少。

       问题3:索引的创建方式(3种)

(1)在自动的创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动的创建对应列的索引。

(2)手动创建:比如对学生的身份证号创建一个索引:

create index index_student_idcard on student(idcard);

        或者为学生表的sn(表示学生编号)和name同时创建索引(复合索引):

create index index_student_sn_name on student(sn,name);

(3)一张表中至少会有一个索引。

  • 如果一张表中有主键,那么主键就是索引。主键索引也称聚簇索引。(大部分情景都是这种情况)
  • 如果是自己手动创建索引,那么就会为这个列或者是多个列创建单独的索引,也叫作非聚簇索引;
  •  如果一张表中没有主键,那么MySql会为每一行生成一个唯一的字段,并用这个字段当做索引。

        ✍2. 选择索引的数据结构是哪种?(面试常考)

        答:MySQL中使用的是B+树作为索引的数据结构。具体从以下四种数据结构分析回答:

(1)Hash

        Hash的查询和插入的时间复杂度都是O(1),但是由于不支持做范围查询(大于和小于 between and 这种操作)因此并不支持做数据库的索引。

(2) 二叉搜索树

      二叉搜索树的时间复杂度是O(logN),O(N)。其中,红黑树是O(logN),因为红黑树可以动态的调整树高,不会出现单边树的情况。但是二叉搜索树也不适合做数据库的索引。原因是二叉搜索树的中序遍历是一个有序数组,它无法控制树的高度,而树的高度决定了磁盘的访问次数。(对于系统来说,所有系统的瓶颈就是磁盘IO)也就是说树的每一层就对应了查询过程中的一次磁盘IO。因此适用于做索引的数据结构一定要能够有效控制树的高度。

(3) N叉搜索树->B树

         B树虽然可以有效降低树高(主要通过规定每一个节点可以存储多少个元素,当节点中达到了规定的元素个数时才去调整,通过这种方式解决树高的问题),但是MySQL仍然没有使用。而是对B树做了优化,使用B+树作为索引。

(4) B+树(MySQL使用)

B+树

          从上述结构中可以观察到B+树主要由以下特点:

1. 非叶子节点中的每个数据都存在于叶子节点中,并且都对应所在叶子节点中的第一条数据。

2. Mysql中的B+树相邻节点是通过链表连接的,这样组织数据更有利于范围查找;

3. 叶子节点中的数据是有序的;

4. N差搜索树,有效的降低了树的高度,从而减少了磁盘IO次数;

5. 在一定的数据范围内,不论查找的元素是什么,查找的效率基本相同。

6. 叶子节点中包含了树中所有节点的真实完整的数据,非叶子节点中包含的是主键(索引)和叶子结点的引用。

        ✍3. 了解几个关于索引的概念

(1)索引最左原则: 在查询的时候一定要在where条件中按照索引的顺序写过滤条件,称为使用索引的最左原则。

(2)索引覆盖:如果索引中包含所有要查询的列,则直接从索引中返回结果,这个现象叫做索引覆盖。

(3)回表查询:当查询的列表中为 * 或者是索引不能完全满足查询结果时,那么会使用Id到主键索引中查询完整的结果,主键索引中包含当前数据行的所有列的值。参考链接


🌟 事务

        ✍1. 什么是事务

        事务就是将一组sql(多个sql)打包在一个整体中一起执行的机制,效果就是这一组sql要么一起执行要么都不执行。

      比如:account (id,   money)

                                A,     1000

                                B,     1000

      如果让A转账100给B用户,那么就要同时执行两条sql语句:

  • update account money = money -100 where id = A;
  • update account money = money +100 where id = B

     ·两条sql语句一起执行。

       开启事务:start transaction;

       主要有两个操作:rollback(回滚)和commit(提交)。

         如果在执行上述sql语句时出现错误,就在binlog中对已经执行的sql做一个回滚操作;如果上述的sql语句执行成功,那么久将这个结果提交到数据库中,此时别的用户才能看见。

        举例:第一步:现在有一个student学生表,里面一共有8条字段。开启一个事务,并新增一条编号为9数据。 

 第二步:执行rollback 操作:可以看出此时数据都回滚了。

 第三步:我们重新插入第9条数据,并提交。此时新开一个终端可以看见新终端也可以查询到插入的新数据。 

        ✍2. 事务的特性 (ACID)

       (1)原子性(Atomicity):事务中的sql要么都执行要么都不执行,通过commit和rollback控制;

       (2)一致性(Consistency):事务执行之前与执行之后要保持正确的结果;

     (3)隔离性(Isolation):多个事务的执行过程中不能互相干扰;

       (4)  持久性(Durability):事务一旦提交就会写入磁盘永久保存,即便是数据库服务故障也不会影响数据的内容。

        ✍3. 事务的隔离级别(重点掌握)

 3.1 隔离级别分类

 3.2 隔离级别现象

(1)脏读

        脏读并不是说数据本身有多不好,而是说读取的过程中出现了问题。 比如事务B读取到了事务A的还没有提交的数据,当事务A回滚后,事务中的所有修改都回滚了,那么事务B读取到的数据就没有意义了,这个现象就称为脏读。

(2)读已提交

        ——> 脏读的解决办法:将数据库的隔离级别设置为read-committed(读已提交)。

        具体操作是在给事务A(写操作的事务)加上一把锁,在写这个事务的时候加锁。当事务提交后释放锁即可。其中,被加锁的事务不能与其他事务共存,写锁也叫排它锁。

 (3)不可重复读 

read-committed(读已提交)存在的问题:不可重复读。

        使用read-committed(读已提交)可以解决脏读问题,但是又会出现新的问题:比如事务提交之后对于该事务来说就结束了,但是对于一个新的事务A在读一条记录时,另一个事务B对这条记录做了修改,那么此时A再读该条记录时,就会发现两次读到的结果不一致,这种现象就叫做不可重复读。

——> 不可重复读的解决方法:将数据库的隔离级别设为repeatable-read(可重复读)

具体操作: 给读的事务也加上一把锁,但是该锁是一把共享锁,多个读锁可以共存。但是由于写锁是排它锁,所以读锁和写锁不能共存,也就是说,再加了读锁之后,不能进行写操作。 

 不可重复读与脏读的区别是:脏读是某一事务读取了另一事务未提交的脏数据,而不可重复读是读起来前一事务提交的数据。

(4)幻读

repeatable read(可重复读)的问题:有可能会出现幻读问题。

也就是说:对于一条记录来说,在读的时候别的事务不能修改这条记录 ,但是可以添加别的记录。那么当事务A对某记录进行修改时,事务B往这个表中添加了一条新的记录或者删除了一条记录,那么当事务A再去查询所有记录时,发现与上次查到的记录条数不一致,这种现象就是幻读。

——>  幻读的解决办法:serializable串行化。

注意:MySQL数据事务的默认隔离级别虽然是可重复读,但是已经最大限度的解决了幻读问题,但还是并没有完全解决,有些场景下还是会出现幻读现象。如果要彻底解决幻读现象,要将事务的隔离级别设置为serializable(串行化),事务一个接一个的执行,完全放弃并发执行,效率也会降低,但是是最安全的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值