数据库索引底层 B+树 and B树 及事务的特性

人生无肠,大肠包小肠

一、B树

B树:又叫B-树(这里是B杠不是B减树!!!)  B树的一个节点可以存储多个key值,实质上也就是个N叉搜索树,N个Key值可以分成N+1个范围区间

 话不多说上图!

 

 其实B树并没有什么特别亮眼的地方,对于数据库索引来说他还不够完美,B树因为每一个节点可以放多个Key值,这样可以大大降低树的高度  (对于数据库来说,高度越高需要访问硬盘的次数就越多)可以减少IO访问次数,提升效率

二、B+树

B+树就是在B树基础上进行改良,使他更加契合数据库索引!!!

上图!

B+树特点:

1.B+树中的N个Key值可以分为N个区间(B树是N+1!!)

2.B+树的节点一定会存储在子节点中,同时也是该节点的最大值

3.B+树的叶子节点存储了整个B+树  最后的叶子结点会用类似链表的方式首尾相连!!!

4.对于除叶子结点外的其他节点,其他节点只会存储一个Key值,不会存储数据库的每一行,占用空间较小,只有最后的叶子节点才会真正存储数据的每一行!!

B+树的优点:

1.由于一个节点可以存储多个Key值,N个Key值可以分成N个区间,树的高度大大降低,减少了IO访问次数

2.对于B+树来说,所有的查询最终都会落在叶子节点上,所以每次查询的速度都是一样的!!具有稳定性 (对于程序员来说是很有用的!!)

3.因为最后叶子节点是用链表组织存储全部数据的,所以在进行范围查找时十分方便,速度大大提高!

4.由于B+树除叶子节点外所有的节点只会存储Key值,占用空间较小,就可能在内存中进行缓存,这样再次查询的速度就大大提高的,还是减少了IO访问次数!!

补充:

上面说的Key值是默认以ID为主键的情况,当表里面有多个主键的时候,比如一个ID 一个name,此时数据还是在ID这颗B+树中存储,还会再创建一个name的B+树,但是name的B+树最后叶子结点就不会再存储每一行的数据了(只有ID的B+树存储),而是存储主键的ID   (这个过程称为回表)

三、MYSQL事务

试想当我们玩游戏的时候,想给游戏里充值一个648(power!!!),我们用微信支付,充值,然后扣钱了,此时这个游戏的数据库突然宕机了或者崩了??,正正好好在你充值完这一条语句后,刚要给你的账户加上点券服务器崩了,你一看游戏里面没到账???这样就很蛋疼了,所以说!数据库就有事务这个办法来解决这种问题

事务的本质:就是把多条语句整合成一条语句,要么都执行成功,要么就都执行失败!!不会出现执行了一半的情况!!

但是需要注意:当我们是事务失败之后,并不是什么都没有发生!!而是将之前的执行过的语句进行“回滚”还原成原来的样子,看上去就跟没发生一样  

举个栗子:比如说在事务中有这两条语句 一句是将数据库中的数学书价格由40改为50,给语文的价格改成40,当我们执行完第一条语句后,数据库挂了!! 数据库就会自己“回滚”,将数学书的价格-10改回40,这样就跟没发生一样了!!   (数据库中有专门用来记录事务的日志,记录事务执行到那一句了!!)

我们就可以总结一下事务的特点!

事务的特点:

1.原子性:也就是事务中的语句要全都成功要么全都失败!!

2.一致性:事务的前后,数据都是靠谱的!

3.持久性:事务的修改的内容都是在硬盘上的,是持久存在的!!

4.隔离性:用来解决并发处理事务时候出现的问题,在一个事务执行,未提交的时候,他对其他事务来说的不可见的,多个并发事务之间有隔离(也就是说多个事务并发进行,互不影响)

数据库处理并发问题

并发就是数据库同时进行多个事务的执行,但是并发执行的时候往往会场出现一些问题,那么有哪些问题呢?数据库是怎么解决这些问题的呢??

脏读问题 

当多个事务要访问表/数据时,如果一个事务要修改一个物品的价格50修改为100,在第一个事务还没提交的时候,但是正在这个时候,另一个事务同时来查询这个物品的价格查询到价格为50,然后第一个事务提交了,价格变成100了,此时两个事务读取到的结果不一样!!  这时第二个事务的读操作就称为“脏读”(读取到的是无效数据)

MYSQL为了解决脏读问题,就引入了给写加锁的机制:也就是在一个事务进行写操作时,另一个事务不可以进行读操作,也就是进行写操作的时候,不可以读(降低了并发性和效率,提高的数据的准确性)

不可重复读问题

举个栗子:当一个事务A修改书A的价格为50 然后提交了(已经引入了给写枷锁),另一个事务B来读这本书的价格(不是一次读取),读着读着还没读完,此时事务又来修改书A的价格为30,又提交了,此时事务B还没读完,前面读到的价格是50,后面读到的价格又成了30,也就是事务B多次读取前后的价格可能不一样了!!!

MYSQL为了解决不可重复读问题,又约定了不可重复读!!!也就是给读加锁,也就是在事务B读的时候,其他事务不可以再次修改这个数据了!!(进一步降低了并发性和效率,提高了数据的准确性!)

幻读问题

在读和写加锁的前提下,如果事务A 读取两次一个数据,读取的数值是一样的,但是结果集不一样!!

还是举个栗子:当一个事务A要读数据,第一次读完之后,再第二次读取的之前,另一个事务B并没有修改原来的数据(已经给写加锁和给读加锁),事务B又新建了一个以前没有的文件,又提交了,最后事务A读取的数据虽然还是那个数据,但是最后看到的却是两个文件!!

MYSQL为了解决这个幻读问题,又搞了个办法,实在没办法了,就只能放弃并发处理事务(串行化!!),只能一个一个处理,这样的效率是最慢的,并发程度也是最低的,但是数据却是最准确的,隔离性也是最强的(最可靠)

总结

本文讲述了MYSQL索引背后的存储方式,和事务的问题,对于并发处理会产生那些问题,MYSQL是如何解决的!!!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值