Mysql 学习分为三个阶段:
- 【SQL基础】:学习sql命令,建表语句,多表查询,等等,SQLBoy
- 【MySQL原理】:学习MySQL 架构,索引,事务,日志,锁,调优等,面试主要考察MySQL原理。
- 【MySQL高可用】:学会MySQL,主从复制,分库分表,高可用,分布式等等,校招需要简单了解,社招需要加强学习。
对于本人情况,着重学习第二个阶段。
基础篇
SELECT执行流程
首先需要认知Mysql的架构设计,第1个是连接器,然后第2个是解析器,第3个是执行器,最后一个有一个存储引擎的这个概念。
然后我们就可以开始讲这个select执行流程了,首先你sql是经过连接器来处理连接,然后第2个它会进行一个查询缓存,但是在八版本的时候已经去除了,因为经过那个长期的检验,发现他这个对效率没有增强的影响,就把它去掉了,然后第2个是解析器,它就是用来解析那个sql,看有没有错误,有错误我就不给你了,然后还有一个优化的过程,有一个优化的过程优化这个sql语句,看要查询哪个索引好,之后有一个执行器就是调用程度引擎去查询具体的数据。
首先会进行连接器进行链接,之后回去缓存里面查找是否有需要的数据,有就返回,没有的话就到分析器,分析语法错误,之后优化器会针对sql生成出执行计划给到执行器去操作引擎获取数据,如果是一条更新语句到了引擎层的话,也会先去找一下buffer pool 是否有需要的数据,如果没有需要去磁盘加载,有的话就先记录旧值到undo log 里面,然后进行修改,记录redo log 到 redo log buffer 里面,事务完成之后会进行一个bin log 的第二段提交。
其实还有一个流程是select 的关键字流程 from -> join -> where -> group by -> having -> order by
MYSQL常见的存储引擎
最常用的其实就两个,一个是Inodb,还有一个是MySAM,这两个区别的话Inodb它是存在磁盘的那个数据,MySAM是存在内存的,然后他们两个的啊优缺点其实现在基本上没有理由去用mysam,因为innodb它的这个经过这个优化呀,啊,还有这些索引结构啥的都要好。
MYSQL一行记录具体是怎么存储的?
他一行记录具体是存在那个主键索引的那个叶子节点里边,然后他那个一行记录的话,它有个row的概念,里面的话具体存了一些数据啊,还有一些头节点啊这些信息,还有可能是锁啊这种一些信息的话,具体的话那肯定是记不住记不住,但是有个大概的概念。
修正,Mysql 操作数据的最小单位是页,聚簇索引的叶子节点其实也是页,然后贴一张图来表明页与行的关系
为什么采用B+树作为索引
其实就问你B+跟hash 和 b树相比的优势是什么
首先为什么要采用b+索,其实它还有另外两种选型的,一种是哈希,一种是b树,首先说一下哈希啊,它的查询效率确实很高,但是它在大数据量的情况下,它的树的高度也很大,我们知道mysql的数据是存放在磁盘,这就带来大量的io操作,所以我们不使用哈希然后说一下b树,因为b数跟b+树最大的区别其实是它的非叶子节点是否会存取数据。那其实在大数据量的情况下,b加速的高度会显得更矮,然后更宽一些,减少了对页的io操作,所以最终我们选择b+树。
索引失效情况有哪些?
最经典的就是,所以有一个最左匹配原则嘛,要根据他的最左匹配原则来进行查询,第2个我在工作中也碰到过,就是对查询的那个字段索引字段进行一个函数啊一些处理,也会让索引失效。嗯,最后一个我在工作中也碰到过,是一个is delete的一个字段,同事误操作把isdeleted全部改成零了,这时候是重构建一下,所以他那个查询效率才提提起来的。
优化索引的方法
其实优化索引总的来说就是两件事:
建最简单有效的索引
查询的时候尽可能利用索引
有一个很重要的原则就是最左匹配吗?不管是再多级索引上还是在字符串索引上,都有这个,建立索引的时候也是要根据具体情况来构建这个索引。
explain各个字段代表的意思
- id :select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
- select_type :查询类型 或者是 其他操作类型
- table :正在访问哪个表
- partitions :匹配的分区
- type :访问的类型
- possible_keys :显示可能应用在这张表中的索引,一个或多个,但不一定实际使用到
- key :实际使用到的索引,如果为NULL,则没有使用索引
- key_len :表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度
- ref :显示索引的哪一列被使用了,如果可能的话,是一个常数,哪些列或常量被用于查找索引列上的值
- rows :根据表统计信息及索引选用情况,大致估算出找到所需的记录所需读取的行数
- filtered :查询的表行占表的百分比
- Extra :包含不适合在其它列中显示但十分重要的额外信息
来自 网络
count(*) 和 count(1) 有何区别?哪个性能更高。
先说结论,count(*) 在底层会被转换为 count(0) ,性能是一样的。
索引篇
事务隔离级别。
之前在wolai.com 已经总结过了,以及三个日志,这里简单在回顾一些(就当是复习了)
- 脏读:读取到其他事务未提交的修改
- 幻读:读取到其他事务已提交的修改(这里的修改更多是指新增和删除)
- 不可重复读:读取到了其他事务已提交的修改(这里指的是数据的修改)
对应四个隔离级别:读已提交,读未提交,可重复读,序列化
MVCC是什么?
直译过来就是多版本并发控制,对事务隔离的一种解决方案。
快照读,当前读
快照读,就是对数据库的某一刻状态定格下来,读取,无视后面的修改。这个是通过MVCC来实现的
当前读:读取最新的数据。
rr 和 rc 隔离级别下,readview 的生成时机
rr 可重复读,只在第一次查询的时候生成readview , rc 读已提交,每次查询都会生成一个readview
undolog 版本链怎么生成的?
每次有事务进行修改的时候,都会生成一个undolog ,在log里面会记录事务ID
readview 具体和undolog 是怎么比较的
生成readview 的时候,会有几个比较重要的参数,
- 当前事务ID
- 未提交的事务ID列表
- 最小的事务ID
- 下一个(最大)事务ID
在读取数据的时候,有一个比较严谨的算法,来跟undolog进行比较,找到最后的我可以读的记录。
比较顺序 最小事务ID -> 最大事务ID -> 事务ID列表
MySQL:基于undo log多版链条实现的ReadView机制,到底是什么_mysql 链条-CSDN博客
MVCC能完全解决幻读问题嘛?
不能,在进行当前读的时候,就不能解决幻读的问题了,为了解决幻读问题,可序列化就是在MVCC的基础上加了一个锁,锁住一个范围,不让别人进行操作。
可重复读隔离级别,完全解决了幻读嘛?
只解决了一部分幻读,如上。
在快照读的情况下解决了一部分,但是无法避免的能读到添加的数据。
一行记录是怎么存储的?NULL值是怎么存储的?变长字段是怎么存储的?
在这边博客里面了解到了大体的一个结构,然后就是行的具体的一个存储的数据,再截个图。
那表空间里面有一个段。段里面放区,区里面再放一个页,页里面再放一个行,每次读取的时候最小单位是一个页,索引结构的最小单位也是一个页。
接下来看一下行的数据格式,重点说几个变长字段长度列表,NULL值列表,就是为了记录真实数据里面,一个字段的长度和它是否为null,然后有一个点就是他们是逆续排放的,第2个有个记录头,标记这个数据是否被删除啊?还有一些其他信息,第3个就是undolog日志里面的啊,重要的信息是id,然后有一个指针指向上一条记录的一个指针。
行溢出怎么办?
假如说一个页存不了一条数据,他就会有一个溢出页,他把那个多出来的数据存到那个溢出页,然后原来的那个页就会腾出一些空间来记录这个溢出页的位置在哪里,这样子来操作。
锁篇
待补充中