数据库
首页 > 数据库> > Mysql底层原理:我愿将毕生功力传授于你

Mysql底层原理:我愿将毕生功力传授于你

作者:互联网

所学越多,所知越少。

一、介绍

数据库就是存储数据的一个地方 有几种不同的存储方式
存储格式: 底层是以页存储的 默认 16kb 所说的b + 树 中间节点一页可以存储很多 叶子节点 一页可以存储就要看数据多大了
重点: 底层 已 b+ 树的格式存储数据页 (理解:已b+树的方式找到数据页) 在页上面存储 已链表链接的行数据(理解:行头中变长列值 的768 个字节作为索引 多的就放在别的里面)
分为数据块索引块
创建表的时候默认以主键在数据库中建一个 b+树索引 将所有数据都放在叶子节点上 以主键作为中间分支的
当创建索引的时候 这个时候是在索引块里面 放一个 b+ 树的叶子节点放的都是这个列的值和主键

数据库的存储引擎: (底层的引擎)

mysql 架构:
在这里插入图片描述

二、缓存:

当请求来到数据库 首先是要查询mysql的缓存的 缓存区分为下面几个

三、索引(为数据存储在硬盘上提供更快的查找提供便利):

3.1索引的存储结构:

1. 中间节点只保存下个节点的引用 不存放数据 所有的数据都存放在叶子节点中  
2. 叶子节点 之间是以链表链接的  这样可以用作范围查询非常快  
3. 所有中间节点都在子节点中 是子节点中的最大或者最小 

3.2 索引类型:

3.3 搜索原理:

select * from user where name = '' and age > 15 and age < 30;  
 hash 表: 将name hash 然后直接找  
 B 树 : 查询 age 等于15 的 然后中序遍历 找到结尾 比较耗时  
 B+ 树: 查询age 等于15 的叶子节点 然后通过叶子链表 直接找到最大数   
 user表  id  name  age  height       id 主键索引   (name,age) 联合索引
 select height from user where name = '张三';       
 这个时候 条件name 是有索引的时候(去索引块里面查询对应的值) 查询到叶子节点上面的值name和id 没有height 这个时候回表查询(去数据块里面根据id)根据id走聚集索引 
 查询到所有的数据将height 返回 

四、存储

存储涉及到的文件后缀名的说明:

4.1表空间:

4.2 idb文件结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDis4iDZ-1611556632291)(../image/mysql数据库存储.png)]

5、日志

日志是mysql非常重要的部分,我们要想了解日志,首先明确上面架构服务端存储引擎端,当更新一个数据的时候日志流程是这样的.

1.执行器从引擎中找到数据,如果在内存中直接返回,如果不在内存中,查询返回
2.执行器拿到数据之后会先修改数据,然后调用引擎接口重新写入数据
3.引擎将数据更新到内存中,同事写数据到redo log中,这时处于prepare阶段,并通知执行器执行完成,随时可以操作
4.执行器生成这个操作的bin log,并调用引擎的事务提交接口
5.引擎把刚刚写完的redo log的prepare阶段改为commit 阶段,更新完成

5.1、Redo log 存储引擎的日志文件:

大白话: 为了提升性能 不会每次修改都会修改磁盘这样慢 会将这些放进缓冲区 但是断电不安全 就会有一个后台的进程去跑 将redo log 持久化到磁盘 用于故障修复
主要用于数据恢复,每次修改和删除操作都会先在这里记录一下 循环写入 有两个指针,这个在binlog 没有commit之前就
吧数据写到磁盘中这样 故障恢复的时候就可以找 这个写进去了 而binlog没有提交的 做故障恢复 由两步分组成

5.2、bin log 服务端的日志文件

大白话: 将所有逻辑以一个追加形式写入一个二进制文件
是一个二进制文件 记录了所有的更改 主要用作记录时间点 对sql 进行了更新 删除操作主要用于

  1. 主从同步 主服务器将这个发送到从服务器
  2. 从服务器执行 同步 还可以用于还原

5.3、undo log 存储引擎的回滚日志

大白话: 在数据的头文件中 存储修改之前的数据 和版本号 这样出现错误了 可以直接回滚
在事务没有提交的时候 每执行一个sql 就生成一个undo log 放在行记录的DATA_ROLL_PTR 中 如果是删除的 直接放在行记录头信息里 标记为删除
事务提交的时候 将undo log 删除

5.4、redo log 和bin log 的不同之处?

1.Redo Log是InnoDB引擎特有的,而binlog是MySQL的Server层实现的,所有引擎都可以使用。
2.Redo Log的文件是循环写的,空间会用完,binlog日志是追加写的,不会覆盖以前的日志。
3.Redo log是物理日志,记录在某个数据页做了什么操作,bin log是逻辑日志,记录了这个语句的原始逻辑

六、事务

事务的原理就是通过日志来实现的,其中最重要的是一致性,其他三个都是为了最终一致性做铺垫.

6.1 事务的特征

6.2 事务的隔离级别

上面的undo log 上是事务没有提交的时候在 行记录上面生成这个记录 但是多个事务一起在操作的时候 就是并发事务的时候 就会出现几种

6.3 事务的锁

Q: 可以怎么实现可重复读?

可重复读是指多次读取的数据都是一样的。实现方式有两种 一种是通过读加锁来实现 一种是通过MVCC来实现
在这里插入图片描述

为什么能可重复度?只要没释放读锁,在次读的时候还是可以读到第一次读的数据。

Q:两个事物对同一条记录操作?

​ 这个时候看是读还是写,如果是读的话 两个事物读取的都是快照 之前的数据 如果是更改的话 那么会对这一行加锁 等这个事务提交了 另一个才能操作。

如何将一个 语句写到 sql 中 update t set a=10 where id=1;
首先可以通过 innodb 引擎架构 链接到mysql client端 验证用户名密码 查询缓存 有没有id为1 的 没有击中缓存(每次查询完之后会把之前的数据放在
buffer pool 缓冲池中) 分析器->优化器->执行器 然后就是底层引擎和数据库打交道了
这个地方比的是 innodb搜索引擎 首先 查询id 为1 的 找到了之后 将 a设置为10 调用写入接口 将数据更新到内存中 redo log中 和在
bin log 中记录一条记录 然后调用事务接口 将数据写入到磁盘中

Q: 为什么不用select * 查询

​ 首先使用select * 查询到非常多不必要的数据 造成网络io 的拥堵
​ 其次 mysql 存储是一页 16kb 系统是4k 读取的 这样查询所有有可能是多读几次的

Q: varchar 和 char 有什么区别, 为什么要用 varchar(255) varchar() 最大长度是多少

​ VARCHAR的最大长度 = (最大行大小 - NULL标识列占用字节数 - 长度标识字节数) / 字符集单字符最大字节数
​ varcchar 是可变长字符串 如果超过存储的长度 不会填充 是以一个字节的位数来存储长度
​ char 是字符串 如果超过存储的长度 是以空格填充的
​ 每个行 最大长度是 65535 个字节
​ 如果是使用 行模式使用的 是 compact 使用768 个字节作为索引 如果超过是需要放在

Q: mysql 对于大字段是怎么存储的,为什么varchar() 为什么要用255 ?

​ 在 COMPACT行模式下 对于大字段存储 是将前 768个字段放在索引页记录上 将其他的部分开20字节指向剩余的位置
​ 而在一个字符是3个字节 所以除以3 是 256 一个字节是 存储长度
​ 第二种说法是 大于256 个字节需要两个字节来存放长度 所以基本上是255 这样节省一点内存

Q:那你知道什么是覆盖索引和回表吗?

​ 当你查询的一条语句中,它查询所需要的字段都在这个索引中 那么就叫他覆盖索引, 这个时候就不需要回表查询,如果没有包含全 这个时候就需要根据id 再通过聚集索引来回表查询

Q: 你知道的mysql 的锁有哪些?

​ 读写锁

Q:你们数据量级多大?分库分表怎么做的?

​ 一个表的数据量很大的时候 肯定会就考虑分表了 一般分表 是以 时间段分表和分字段分表(将一些大字段加到另一个表中) 如果查询跨表的就联合中间表查询

Q: 分表后 id 是怎么保证唯一的?

​ 一般是分布式id服务 保证id 的唯一 雪花算法等 还可以指定每个表的唯一字段 比如订单号作为主键

Q: 为什么myisam 比innodb 读的速度快?

​ 如果是非主键查找 innodb 是找到了 需要回表查找 而myisam 直接叶子节点 是 offset 直接物理地址 要快 innodb 支持事务 要维护 mvvc 也是一个原因

Q: count(1) count(*) count(id) count(字段) 哪个快

count(1)和count(*) 这两个是一样的 获取到列 不拿里面的值 只是统计 count(id) 取这个列的id 的值 不为空 则计数 count(字段) 按照这个字段查找 找出这个字段 不为空则 计数
执行效率对比:count(字段) < count(主键) < count(1)

Q: 索引是越多越好吗 为什么 建索引有什么标准吗

当索引多了的话 查询和更新就会变慢,如果主键索引没有规律的话,可能每次更新和插入都会重排索引,所以一般索引最好不要超过八个

标签:存储,功力,log,事务,我愿,索引,Mysql,数据,id
来源: https://blog.csdn.net/hgdzw/article/details/113111945