MySQL 索引和事务

一.索引

索引,本质上相当于书的目录。通过目录,就可以快速的找到某个章节对应的位置。索引的效果,就是为了加快查找的速度。索引会提高空间的开销,构造索引,是需要额外的硬盘空间来保存的。但是在数据库操作中,查找操作是比增、删、改操作要多很多的。引入索引还是划算且有必要的。

1.查看索引。

创建一个学生表,使用index来查看当前表的索引:

表里有主键,主键这一列就会自动创建索引,unique和foreign key也会自动创建索引。

2.创建索引

如果查询的时候,很多名字是按照名字来查询的,这个时候就需要根据名字这一列去创建一个索引了:

 针对名字的这列索引就创建好了。注意:创建索引这件事最好是在表创建之初就把索引给创建好,否则,如果是针对一个表中已经有很多记录的的表来创建索引,是会吃掉大量的磁盘IO,属于危险操作!

3.删除索引

 和刚才的创建索引类似,删除索引时也可能会吃掉大量的磁盘IO,也是一个比较危险的操作!总的来说,最开始设计数据库的时候,就要规划好。要是已经有很多数据了就要谨慎操作。

把索引创建好之后,不需要手动使用,直接查询的时候就会自动的来走索引。

那么,在MySQL中,索引的数据结构是什么呢?首先我们可能想到的是哈希表。但是哈希表是不适合做数据库的索引的!因为哈希表只能比较相等,无法进行< >这样的范围查询。数据库是经常需要进行范围查询的。其次我们可能会想到二叉搜索树,考虑最坏情况(单支树)时,时间复杂度可以达到log(n)。如果这个树比较平衡,例如AVL树,红黑树,时间复杂度可以达到log(n)。二叉树是可以进行范围查询的,但是很遗憾,数据库的查询并没有使用二叉搜索树。二叉意味着当元素个数多了的时候,树的高度就会变高,而树的高度就决定了查询的时候元素的比较次数。排除了二叉搜索树,接下来合适的就应该是N叉搜索树了。对于N叉搜索树,每个树的结点上多个值,同时有多个分支,树的高度就降低了。N叉搜索树的一种典型实现,叫做B树。B树已经可以比二叉搜索树更加适合做数据库的索引了,但是还可以进一步改进。在此引入了B+树,是对B树进行了进一步的改进。B+树,就是为了索引这个场景量身定做的数据结构。

B+树也是一个N叉搜索树,每个节点上可能吧包含N个key,N个key划分出N个区间,最后一个Key就相当于最大值了。B+树的父元素的Key会在子元素中重复出现,并且是以最大值姿态出现的。这种重复出现,就可以让叶子结点包含所有数据的全集!(非叶子结点中所有值都会在叶子节点中体现出来),然后会把叶子结点用类似于链表的方式首尾相连。如图:

上述B+树的特点就带来了一些好处:

1.作为一个N叉搜索树,高度降低下来比较的时候,硬盘IO的比较次数就少了,更适合进行范围查询。

2.所有的查询都是要落在叶子节点上,无论查询哪个元素,中间比较的次数都差不多,查询操作比较均衡。

当前这个B+树这个结构,只是针对MySQL的InnoDB(最主流使用的一种存储引擎)这个数据库引擎中所使用的数据结构,对于不同的数据库,不同的引擎,里面存储的数据结构还可能存在差异.

二.事务

事务属于是能够把多个SQL给打包到一起,变成一个整体的。例如1给2转账,1的余额-50的同时需要给2的余额加50;再比如下订单,商品里的库存-1的同时,订单表里的库存就要+1。上述这两种操作就需要把多个操作打包成一个整体,要么全部执行完,要么一个都不执行。打包成整体这种操作就称为“原子性”,也是事务最最核心的特性!我们想一下,加入执行中间出错了,就一条也不让执行,好像逻辑上有问题.注意,这里不是一条都没有执行.而是自动的恢复成了原来的样子。这里面涉及到一个关键操作叫做“回滚”。回滚操作也就是把执行过的操作逆向恢复回去,类似于电脑上的撤销操作。数据库会把执行的操作都记录下来,如果某个操作出错就会把事务中前面进行过的操作进行回滚,如果前面是插入,回滚就是删除;前面是删除,回滚就是插入......那么有了这种操作,是否就不担心删库删表了呢??不是!删库删表仍然是危险操作!假设数据量极大,此时是不可能花同样大的空间来记录每个数据都是咋来的。

上面介绍的是事务中最核心的特性:原子性。实际上,数据库的事务有四大特性。其他三个特性分别是:一致性,持久性,隔离性。

1.一致性

一致性就是在事务执行前后,都需要是数据合法的状态。比如刚刚说过的转账,不能说转账的过程出错了导致钱丢了的情况。

2.持久性

事务所产生的修改都是会写入硬盘的。重启主机或者断电等操作,并不会影响事务工作。

3.隔离性

隔离性就是一个数据库服务器同时执行多个事务的时候,事务之间的相互影响程度。这里的多个事务,就比如客户端-服务器这种结构的数据。一个服务器可以给多个客户端提供服务,这多个客户端彼此之间是并发执行的关系。如果隔离性越高,就意味着事务之间的并发程度越低,执行效率越慢,但是数据的准确性是越高的。如果隔离越低,就意味着事务之间的并发程度越高,执行效率越快,但是数据的准确性是越低的。MySQL给我们提供了不同的挡位可以控制隔离性的高低/并发程度的高低/执行效率的高低/数据准确性的高低。如何取舍还是要根据具体问题具体分析。

这里,MySQL提供了四个隔离级别:

1)read uncommitted 不做任何限制,事务之间可以随意并发执行,并发程度最高,隔离性最低。会产生脏读+不可重复读+幻读问题。

2)read committed 对写操作加锁。并发程度降低,隔离性提高了。解决脏读问题,存在不可重复读+幻读问题。

3)repeatable read对写和读操作加锁,并发程度再次降低,隔离性继续提高。解决脏读+不可重复读问题,可能存在幻读问题。

4)serializable 严格串行化。并发程度最低,隔离性最高,解决了脏读+不可重复读+幻读问题,执行速度最慢。

开发中就可以根据当前要解决的问题,来决定使用哪个隔离级别。这里是通过MySQL配置文件来调整的。

这时候大家可能会问,什么是脏读、不可重复读、幻读?在这里举个例。

脏读:假设一名老师正在写教案,一名同学正好在看,看完之后这名同学就走了,同学走之后,老师就把这个教案给扔了。同学和老师这两个事务是完全并发的,没有任何限制,这种情况就称为脏读。解决脏读问题的办法就是降低并发性,提高隔离性。具体来说,就是给写操作加锁,比如在老师写教案的时候,同学是不能看的,等老师把教案保存下来之后,同学再来看。

不可重复读:现在已经约定好了写加锁。那么又会出现什么问题呢?老师在写教案,有个同学来看,突然想起来现在还不可以看。所以同学就在这等,等到老师把教案保存后,同学开始读。但是当同学正在读的时候,老师突然有了新想法,与是老师修改教案,重新提交了个版本。导致这个同学读了一半,内容突然就变了!这就是不可重复读。在一个事务中,连续两次读到的数据不一致。解决方法是,给读操作也加锁。同学在读教案的时候,老师不能修改。

幻读:当前已经约定了写加锁和读加锁。但是新的问题又出现了。当老师看到同学在读教案了,虽然老师不能去修改当前的教案,但是老师可以新增/删除一个其他的教案。此时的同学读的代码内容没变,但是他发现,教案的数量变了。这个问题称为幻读。在同一个事务中,两次读到的结果集不同,要想解决幻读问题,要实现串行化,彻底的舍弃并发,只要同学在读,老师就什么也不能做。

事务的四个基本特性,前三个都比较好理解,隔离性就比较复杂。并发也是我们后续学习的重点。如有错误,欢迎指正!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚报大街-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值