mysql深入底层了解
Posted 黄昏单车
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql深入底层了解相关的知识,希望对你有一定的参考价值。
索引数据结构
# 索引的本质:帮助mysql高效获取数据 排好序 的 数据结构
Myisam存储引擎索引实现
# 分三个文件存储:
1:frm存储表结构
2:MYD存储表数据
3:MYI存储表索引数据
底层查找过程:先通过MYI索引数据结构找到对应索引,拿到磁盘文件地址,通过地址定位MYD数据所在行记录
InnoDB存储引擎索引实现
# 分二个文件存储:
1:frm存储表结构
2:ibd存储数据和索引
# 为什么建议InnoDB表必须建主键?
因为索引数据必须要有B+Tree结构组织数据,没有建有主键,会从表中找唯一列作为B+Tree结构存储
如果没有唯一列,会默认建立隐藏列Rowid自维护,用Rowid进行B+Tree组织数据结构,所以为了避免减少
数据库的性能维护,必须建主键。
# 为什么推荐使用整型的自增主键?
整型可以直接比较大小,效率高,占用空间小,字符串比较需要转成ascii码逐位比较,
自增问题例如5,7,再插入一个6的时候,为了保持自增的顺序性,会在5,7之间插入元素,如果满了之后会分裂
重组索引变成5,6,7...,造成性能损耗
二叉树
# 特性
1)k-v结构,k就是数据,v就是索引所在行磁盘文件地址
2)右边的子节点大于父节点,左边的子节点小于父节点
注意:不适合单边增长数据,例如自增id(1,2,3,4,5,6...)
红黑树(二叉平衡树)
B-Tree
B+Tree
每个节点最大16kb
假如索引用bigint类型:占据8b,磁盘文件地址6b,根节点大概可以存储1170个索引,子节点一样
假如叶子节点1个索引1kb,最终1170 * 1170 * 16,大概两千万
根节点和子节点会常驻内存,不需要进行磁盘读取,最终只需要一次磁盘I/O交互
Hash
bin log和redo log日志
# Bin log归档日志(逻辑日志)
1:二进制日志
2:在Mysql的server层实现(引擎共用)
3:记录的是一条语句的原始逻辑
4:不限大小,追加写入,不会覆盖以前的日志
# 开启bin-log
查看是否开启:show variables like '%log_bin%';
mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | OFF |
| log_bin_basename | |
| log_bin_index | |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-------+
6 rows in set
我是在本地使用的phpstudy,所以修改my.ini如下,由于存在了datadir,所以只需要配置:
log-bin=mysql-bin即可,server_id=1默认存在,不用动
[mysqld]
datadir=D:/phpstudy_pro/Extensions/MySQL5.7.26/data/
log-bin=mysql-bin
server_id=1
注意5.7以及更高版本需要配置本项:server-id=123454
mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------------------+
| Variable_name | Value |
+---------------------------------+---------------------------------------------+
| log_bin | ON |
| log_bin_basename | D:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\mysql-bin
| log_bin_index | D:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\mysql-bin.index
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+---------------------------------------------+
6 rows in set
# bin-log命令(以下命令根据自己的文件目录所在清空变化)
sync_binlog:设置为1,表示每次事务binlog都将持久化到磁盘
flush logs:会多一个最新的bin-log日志
show master status:查看最后一个bin-log日志的相关信息
reset master:清空所有的bin-log日志
查看 bin-log内容:
/usr/local/mysq1/bin/mysqlbinlog --no-defaults
/usr/local/mysql/data/mysql-bin.000001
恢复日志(需要分开两个日志:一个插入,一个清空):
/usr/bin/mysqlbinlog --no-defaults /var/run/mysqld/mysql-bins.000005
| mysql -u root -p laravel
恢复指定位置段数据(从BEGIN前一个end_log_pos 348,到COMMIT前end_log_pos 424):
/usr/bin/mysqlbinlog --no-defaults /var/run/mysqld/mysql-bins.000005
--stop-position="424" --start-position="348" | mysql -u root -p laravel
恢复指定日期段数据(日期时间范围要小于开始时间,大于结束时间,不能等于):
/usr/bin/mysqlbinlog --no-defaults /var/run/mysqld/mysql-bins.000005
--stop-datetime="2021-05-10 02:07:30" --start-datetime="2021-05-10 02:07:00"
| mysql -u root -p laravel
# Redo log重做日志(物理日志)
记录InnoDB存储引擎的事务日志
MySQL的WAL机制(Write-Ahead Logging),先写日志再写磁盘
文件名:ib_logfile*
# Redo Log写入原理
以循环方式写入日志文件,不断的写与擦除,文件1写满时,切换到文件2,
文件2写满时,再次切换到文件1。
writepos当前记录的位置,循环边写边后移
checkpoint当前要擦除的位置,循环边写边后移
以上是关于mysql深入底层了解的主要内容,如果未能解决你的问题,请参考以下文章