展示
作为一个平民作者,在文化的底层输出,卑微的记录自己的学习经历,在社会生活的压迫下,终于无法掩盖自己的脆弱(宇哥说我菜,我说他jb🤡)。
生而为人,必当思己之弊,优己之德才,以善对人,人言汝jb,汝不怒之也,独言一句:Shut up Fuck you!
下面开始正文,🐂🐴冲冲冲!
存储引擎
什么是存储引擎呢?
如果你此时此刻还不知道什么是存储引擎,那么说明你以前就不知道什么是存储引擎!🤡
一句透彻的分析,说出了🐂🐴们的实力,我们开始走入存储引擎,let,s go,苏喂苏喂苏喂!
sql
Create Table: CREATE TABLE `engine_demo_table` ( `i` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
建表的语句就可以选择存储引擎!
mysql底层存储数据的功能,负责存储数据、给数据建立索引、更新数据、查询数据,不同的存储引擎有不同的特点,我们只介绍比较常用的存储引擎里,最不常用的两个!😁
InnoDB
InnoDB是一个健壮的事务型存储引擎,他的特点是支持事务,可以支持行级锁🔐,外键约束(不一定用的到),支持自动增加列AUTO_INCREMENT属性,5.7开始InnoDB成为MySQL默认的存储引擎。
需要事务支持,有较高的并发读取频率,可以选择InnoDB存储引擎。
MyISAM
不太常用了,具体就是表级锁🔐,不支持外键,不支持事务,我们知道这些就行了,面试够用,谁还继续研究啊,那不是🐂🐴吗?
优缺点对比
锁机制不同:
表锁,即使操作一条记录也会锁住整个表,不适合高并发的操作
行锁,操作时只锁某一行,不 对其它行有影响,适合高并发 的操作
MyISAN只缓存索引,不缓存 真实数据
InnoDB不仅缓存索引还要缓存真实数 据,对内存要求较高,而且内 存大小对性能有决定性的影响
索引
为什么要使用索引
不使用索引找数据的时候,非常的耗时,就像你去图书馆找书,没有分类,这jb不是垃圾堆🐴
那我们如果使用二叉树来存储数据,是不是好多了,这就索引的意义所在,快速找到数据,并占有他😎
这个就是B+树的结构了,最下层是我们存储的数据,也就可以想象成表里的一条条数据组成的数据页,第二层是把每页最大的页码又重新进行分页了,第三层是又进行了一次分页,这样我们就能很快的找到想要的数据,而且大家要注意数据都是有顺序的,这样非常方便我们来进行排序查询语句,同时呢建立索引的数据,修改和删除会导致索引变动,造成底层的IO成本哦。
索引分为几种:
聚簇索引:
🐂🐴又要问了,这是什么宇哥🐢索引,没有听过啊!
当然了,菜鸟谁知道这个,知道这个,你还是菜鸟吗?你对的起这两个字🐴,来今天我们就从菜鸟迈入到垃圾的阵营里。
当你创建表的时候,用的是InnoDB存储引擎,那就会默认生成一个聚簇索引,默认按照主键去排序成一个顺序链表,采用B+树的数据结构来存储,如果没有主键呢(不加主键那么🐂B,你是宇哥🐢吗?),当然会选择一个唯一字段来进行排序,如果没有唯一字段就会默认生成一个隐藏主键字段去进行排序,这里有个小彩蛋了,主键自增可以加快效率奥,因为主键不是自增的没有规律,那就会产生不必要的IO操作。
二级索引
就是和聚簇索引一样的数据结构,区别在于数据页存储的是主键,需要回表才能拿到数据,也就是通过主键去聚簇索引拿到完整的数据,来下面看图👇🏻
这就很清楚了,我们二级索引底层是key(分页数)+pk(主键)。
这里提示大家通过主键去修改数据会比二级索引要快哦,因为省去了回表的操作!
联合索引
数据结构也是和二级索引差不多,只是多个字段进行B+树的方式来储存,区别在于,他会按照第一个字段进行优先排序,然后第一个字段相同,在进行第二个字段排序,这也就是我们常说的,前面的字段会生效的原因了。
MyISAM和InnoDB索引对比
MyISAM没有聚簇索引,都是二级索引,每次查询都需要回表,但是数据页里存储的是地址,回表非常快,没有聚簇索引,数据和索引是分离存储的。 InnoDB有聚簇索引,且是必须存在的,数据和索引是存储在一起的。
赠送小知识点,HASH结构
Hash结构就是类似key-Value的存储方式,把你要保存的数据,通过算法获取一个唯一结果,通过这个结果去查询、插入、删除,他的复杂度要更低是o(1),B+数需要从上向下一次查找。
还有就是hash结构的key计算后结果比如是17还有一个key是33,用取模16这种方式来找存储点可能是存储到一个位置,专业名词叫做"碰撞"💥,那这种情况怎么处理呢,这时我们会用链表的解决方式来处理,存储到相同位置的数据,用链表来存储。
问题来了Hash的速度快,我们为什么不用hash结构来存储数据呢?小🐂🐴你的问题超纲了您知道吗?
原因:
Hash结构能满足=、<>、in的查询,这样肯定查找效率更高,但是我们想如果来一个order by 兄弟们,hash是无序的啊!这可难办了?
🤠 我敲,难办就别办了,而且联合索引hash是不支持的,对于我们平时根据type=1这样范围的查找,hash也是非常慢的,如果用b+数,那不就飞快!
那hash结构怎么优秀我们是不是也要利用一下啊,InnoDB能就提供了这样一个功能,自适应Hash索引 ,当一个数据被经常使用,那么这个数据的地址,会被存储到Hash表里,这样我们在享受着B+树的福利上,也用到了Hash的特点真是:宇哥🐢去健身房吃炸鸡,什么都想要啊!
事务
先来个大家都懂的,也是面试比较常问的:说一下事务的四个特性?
一看这面试官挺在试探你呢,这个都过不了,兄弟们,此场面试,G已!
让我们把这个4个特性先背熟!!!
4个特性:
原子性:要么成功,要么失败,没有别的结果,联想记忆法来了!
原子性就等于原子弹啊,要么全部融化掉,要么就是投掷失败,没有别的选择,就像广岛的原子弹,我敲,威力必须是2222,起码是2222!
一致性:从一个状态转换到另一个状态,什么意思呢,例如从帐户A转一笔钱到帐户B上,如果帐户A上的钱减少了,而帐户B上的钱却没有增加,那么我们认为此时数据处于不一致的状态。
当然了,原子弹炸了,必须要造成伤害,或者是爆炸失败(回滚),没有可能说扔了原子弹,还爆炸了,没有造成伤害,这不是二踢脚吗bro!
隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
这个就抽象一点了,也不能并发扔原子弹啊,但是我来告诉你,原理都是一样的,A原子弹爆炸了,B原子弹就没有伤害了吗?
当然事务还有隔离级别:
- 读未提交:read uncommitted 读到别的事务没提交的数据,很严重的。
- 读已提交:read committed A事务在进行中,B事务提交了,A事务读到了B事务的数据,不符合我们的隔离性啊
- 可重复读:repeatable read A事务查询表有5条数据,进行了加锁,B事务添加一条数据,A事务又查询,哇多了一条这就是幻读,不加锁的数据没法控制啊bro!
- 串行化:serializable Serializable 是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。 都排队执行了,还有什么效率,这不公园买票吗?
持久性:一个事务一但提交了就是永久性的,数据会持久化到磁盘。
原子弹爆炸了💥就是伤害你,你只能一笑而过,回滚?,对不起他已经爆炸了!
那事务有这4个特性,是怎么实现的呢,整!
事务如何实现的?
利用回滚日志(undo log) 和 重做日志(redo log) 两种表实现事务,并实现 MVCC (多版本并发控制) ; 下面举个例子,用updata的场景来说,因为insert不涉及到多版本。
- 将修改后的数据存入缓冲池(Buffer Pool)中,等待刷脏。
- 在Log Buffer中写入重做日志(Redo Log),并将日志状态设置为Prepare。
- 返回MySQL服务层,记录BinLog日志。
- 将Log Buffer中的日志文件状态设为Commit,并等待日志文件存入盘中。
下面我们来分析一下redo log 和undo log的作用:
redo log:叫做重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中。
简单的来说呢,就是一个事务,修改了数据,先要写redo日志,然后存储到缓存里,然后事务提交了,刷新到磁盘里。
undo log :undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。
这篇文章写的时间有点长了,好多内容都忘了,最近要重新找回状态,下一章我要写MVCC解决幻读问题、binlog、主从搭建,然后希望大家多多关注,我会超过宇哥🐢的!