mysql内部结构和InnoDB底层原理

news2025/1/13 10:16:29

一、mysql内部结构

mysql总体上分为客户端、Server层、引擎层,具体如下图:

1、连接器

一般客户端通过jdbc、navicat等工具发送请求连接到mysql服务端,完成TCP三次握手后,连接器就开始认证身份,如果身份认证成功,所有操作将依赖此时读取到的权限,因此权限的确定是一连接就读取确认了,为什么不实时读取权限,因为如果并发量大的情况下,势必要暂停用户请求,然后才能更改权限,性能上会有很大的损耗

CREATE USER 'username'@'host' IDENTIFIED BY 'password'; #创建新用户
grant all privileges on *.* to 'username'@'%'; #赋权限,%表示所有(host)
flush privileges #刷新数据库
update user set password=password('123456') where user='root';#(设置用户名密码)
show grants for root@"%"; #查看当前用户的权限
show processlist;#查看连接状态命令
kill Id值#关闭连接命令

2、查询缓存

server端的查询缓存,存储结构是key、value形式,key是sql语句,value是查询的结果集,每次对表执行一次更新操作,这个表所有的查询缓存都会失效,所以缓存很难命中,基本不用,mysql8这个功能已经被去除了;一般对于不需要经常修改的字典表可以用这个功能(现在一般用redis做字典缓存),可以在my.cnf文件设置query_cache_type=DEMAND

在mysql8版本以下的可以在my.cnf中配置:

#query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE关键词时才缓存
query_cache_type=2
select SQL_CACHE * from test where ID=5;#query_cache_type为2的用法

show global variables like "%query_cache_type%";#查看当前mysql实例是否开启缓存机制

3、分析器

词法分析:MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”

语法分析:根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。如果你的语句不对,就会收到“You have an error in your SQL syntax”的错误提醒

4、优化器

mysql会根据内部计算是否要选索引,或者join查询时选择哪个是驱动表,以及mysql其它的优化

5、执行器

判断是否有当前表的权限,如果没有,就会返回没有权限的错误,如果有权限,mysql就会打开表,根据表设置的存储引擎类型调用对应的存储引擎接口(如果是在查询缓存中命中,会在查询缓存返回结果时做权限认证)

二、InnoDB底层原理与mysql日志机制

1、undo log

InnoDB对undo log文件的管理采用段的方式,也就是回滚段(rollback segment)。每个回滚段记录了1024个undo log segment,每个事务只会使用一个undo log segment

在mysql5.5的时候,只有一个回滚段,那么最大同时支持的事务为1024个。在mysql5.6开始,InnoDB支持最大128个回滚段,故其支持同时在线的事务限制提高到了128*1024

innodb_undo_directory:设置undo log文件所在的路径。该参数的默认值为"./",即innodb数据文件存储位置,目录下ibdata1文件就是undo log存储的位置。
innodb_undo_logs: 设置undo log文件内部回滚段的个数,默认值为128。
innodb_undo_tablespaces: 设置undo log文件的数量,这样回滚段可以较为平均地分布在多个文件中。设置该参数后,会在路径innodb_undo_directory看到undo为前缀的文件。

undo log日志什么时候删除

新增类型的,在事务提交之后就可以清除掉了。

修改类型的,事务提交之后不能立即清除掉,这些日志会用于mvcc。只有当没有事务用到该版本信息时才可以清除。

2、redo log

innodb_log_buffer_size,查看redo log buffer大小参数,默认16M,最大值4096M,最小值1M

show variables like '%innodb_log_buffer_size%';

innodb_log_group_home_dir:查看redo log文件存储位置参数,默认值为"./",即innodb数据文件存储位置,其中的ib_logfile0和ib_logfile1即为redo log文件

show variables like '%innodb_log_group_home_dir%';

innodb_log_files_in_group:查看redo log文件的个数,命名方式如:ib_logfile0,ib_logfile1...ib_logfilen。默认两个,最大100个

show variables like '%innodb_log_files_in_group%';

innodb_log_file_size:查看单个redo log文件大小,默认值为48M。最大值为512G,注意最大值指的是整个redo log系列文件之和,即(innodb_log_file_in_group*innodb_log_file_size)不能大于最大值512G

show variables like '%innodb_log_file_size%';

redo log磁盘写入过程:

redo log从头开始写,写完一个文件继续写另一个文件,写到最后一个文件末尾就又回到第一个文件开头循环写,如下面这个图所示

write pos是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头

checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件里

write pos和checkpoint之间的部分就是空着的可写部分,可以用来记录新的操作。如果write pos追上了checkpoint,表示redo log写满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把checkpoint推进一下

innodb_flush_log_at_trx_commit:这个参数控制redo log得写入策略,它有三种可能取值:

  • 设置为0:表示每次事务提交时都只是redo log留在redo log buffer中,数据库宕机可能会丢失数据
  • 设置为1(默认值):表示每次提交事务时都将redo log直接持久化到磁盘,数据最安全,不会因为数据库宕机丢失数据,但是效率稍微差一点,线上系统推荐这个设置
  • 设置为2:表示每次事务提交时都只是把redo log写到操作系统的缓存page cache里,这种情况,如果数据库宕机是不会丢失数据的,但如果操作系统宕机了,page cache里面的数据还没来得及写入磁盘文件的话就会丢失数据

InnoDB有一个后台线程,每隔1秒,就会把redo log buffer中的日志,调用操作系统函数write

写到文件系统page cache,然后调用操作系统函数fsync持久化到磁盘文件

redo log写入策略参看下图:

# 查看innodb_flush_log_at_trx_commit参数值:
show variables like 'innodb_flush_log_at_trx_commit';
# 设置innodb_flush_log_at_trx_commit参数值(也可以在my.ini或my.cnf文件里配置):
set global innodb_flush_log_at_trx_commit=1;

3、binlog

binlog二进制日志记录保存了所有执行过程的修改操作语句,不保存查询操作。如果mysql服务意外停止,可通过二进制日志文件排查,用户操作或表结构操作,从而来恢复数据库数据

启动binlog记录功能,会影响服务器性能,但是如果需要恢复数据或主从复制功能,则好处大于对服务器的影响

# 查看binlog相关参数
show variables like '%log_bin%';

 mysql5.7默认是关闭的,8.0默认是打开的。上图的log_bin的值是OFF就代表binlog是关闭状态,打开binlog功能,需要修改配置文件my.ini(windows)或my.cnf(linux),然后重启数据库

在配置文件中的[mysqld]部分增加如下配置:

# log-bin设置binlog的存放位置,可以是绝对路径,也可以是相对路径,这里写的相对路径,则binlog文件默认会放在data数据目录下
log-bin=mysql-binlog
# Server Id是数据库服务器id,随便写一个数都可以,这个id用来在mysql集群环境中标记唯一mysql服务器,集群环境中每台mysql服务器的id不能一样,不加启动会报错
server-id=1
# 其他配置
binlog_format = row # 日志文件格式,下面会详细解释
expire_logs_days = 15 # 执行自动删除距离当前15天以前的binlog日志文件的天数, 默认为0, 表示不自动删除
max_binlog_size = 200M # 单个binlog日志文件的大小限制,默认为 1GB


log_bin:binlog日志是否打开状态
log_bin_basename:是binlog日志的基本文件名,后面会追加标识来表示每一个文件,binlog日志文件会滚动增加
log_bin_index:指定的是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录。
sql_log_bin:sql语句是否写入binlog文件,ON代表需要写入,OFF代表不需要写入。如果想在主库上执行一些操作,但不复制到slave库上,可以通过修改参数sql_log_bin来实现。比如说,模拟主从同步复制异常。

 重启数据库后我们再去看data数据目录会多出两个文件,第一个就是binlog日志文件,第二个是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录

当然也可以执行命令查看有多少binlog文件

show binary logs;
#查看当前正在使用的是哪一个binlog文件
show master status;

binlog的日志格式

用参数binlog_format可以设置binlog日志的记录格式,mysql支持三种格式类型:

  • STATEMENT:基于sql语句的复制,每一条会修改数据的sql都会记录到master机器的binlog中,这种方式日志量小,节约IO开销,提高性能,但是对于一些执行过程中才能确定结果的函数,比如UUID()、SYSDATE()等函数如果随sql同步到slave机器去执行,则结果根master机器执行的不一样
  • ROW:基于行的复制,日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改记录下每一行数据修改的细节,可以解决函数、存储过程等在slave机器的复制问题,但这种方式日志量较大,性能不如STATEMENT。举个例子,假设update语句更新10行数据,STATEMENT方式就是记录这条update语句,ROW方式记录被修改的10行数据
  • MIXED:混合模式复制,实际就是前两种模式的结合,在MIXED模式下,mysql会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在STATEMENT和ROW之间选择一种,如果sql里有函数或一些执行时才知道结果的情况,会选择ROW,其它情况选择STATEMENT,推荐使用这一种

binlog写入磁盘机制

binlog写入磁盘机制主要通过sync_binlog参数控制,默认值是0

  • 为0的时候,表示每次提交事务都只write到page cache,由系统自行判断什么时候执行fsync写入磁盘。虽然性能得到提升,但是机器宕机,page cache里面的binlog会丢失
  • 为1时,表示每次提交事务都会执行fsync写入磁盘,这种方式最安全
  • 还有一种方式,可以设置为N(N>1),表示每次提交事务都write到page cache,但积累N个事务后才fsync写入磁盘,这种如果机器宕机会丢失N个事务的binlog

删除binlog日志文件

删除当前的binlog文件
reset master;
# 删除指定日志文件之前的所有日志文件,下面这个是删除6之前的所有日志文件,当前这个文件不删除
purge master logs to 'mysql-binlog.000006';
# 删除指定日期前的日志索引中binlog日志文件
purge master logs before '2023-01-21 14:00:00';

查看binlog日志文件

可以使用mysql自带的工具命令mysqlbinlog查看binlog日志内容

# 查看bin-log二进制文件(命令行方式,不用登录mysql)
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 

# 查看bin-log二进制文件(带查询条件)
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 start-datetime="2023-01-21 00:00:00" stop-datetime="2023-02-01 00:00:00" start-position="5000" stop-position="20000"

binlog日志文件恢复数据

当前表数据如下图:

删除两条数据后再来查询

 如果不清楚binlog放在哪可以用show variables like '%log_bin%';查一下,查看binlog内容:

mysqlbinlog --no-defaults -v --base64-output=decode-rows /var/lib/mysql/binlog.000001

 对于# at 720就是要恢复位置,SET TIMESTAMP要恢复的时间,需要把时间戳转换成时间格式

 位置号恢复

mysqlbinlog  --no-defaults --start-position=311 --stop-position=751 --database=test /var/lib/mysql/binlog.000001 | mysql -uroot -p123456 -v test

如果有这个警告恢复不了可以这样写

mysqlbinlog  --no-defaults --start-datetime="2023-06-27 22:24:47" --stop-datetime="2023-06-27 22:25:41" --database=test /var/lib/mysql/binlog.000001 | mysql -uroot -p -v test

还可以使用mysqldump命令工具每天凌晨的时候定时备份数据,备份出来的文件是具体的sql,最近一次的全量备份再加上binlog提交的事务来恢复数据

mysqldump -u root 数据库名>备份文件名;
mysqldump -u root 数据库名 表名字>备份文件名;  #备份整个表

例:
mysqldump -u root -p test>test.sql; test.sql生成出来的sql文件

为什么会有redo log和binlog两份日志呢?

mysql早期使用的是myisam存储引擎,要保证crash-safe(任何时间服务器异常重启,保证事务的完整型),只能使用InnoDB存储的redo log和undo log来实现

假设一条数据被删了,事务一提交redo log就无法找回了,只能通过binlog

4、错误日志

当数据库故障导致无法运行时使用下面命令

# 查看错误日志存放位置
show variables like '%log_error%';

5、通用日志查询

通用日志查询会记录用户的所有操作,一般不开启,定位问题时临时开启

show variables like '%general_log%';
# 打开通用查询日志
SET GLOBAL general_log=on;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693752.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构-串、数组和广义表

数据结构之串、数组和广义表 串的定义一、串的顺序存储结构1.1、串的链式存储结构1.2、串的模式匹配算法1.2.1、Brute-Force简称为BF算法1.2.2、KMP算法 数组的定义2.1、数组的顺序存储结构2.2、数组的特点:结构固定-----维数和维界不变2.3、特殊矩阵的压缩存储 广义…

密码学—Kasiski测试法Python程序

Kasiski Kasiski是辅助破解Vigenere的前提工作,Kasiski是猜测加密者使用Vigenere密码体系的密钥的长度,Kasiski只是猜测长度而已,所以说是辅助破解Vigenere 若密文中出现两个相同的密文段(密文段的长度m>2),则它们对应的明文&…

leetcode第66题:加一

题目 这是一道简单的小题,自己却也没写出来。。。逆序遍历数组digits,用carry标记当前元素是否需要进位(0不要,1要)。 若carry1,则当前元素要么置0,要么自加1。自加1之后,再也不需要…

【深入了解Spring Cloud Alibaba Nacos:服务注册和配置中心】—— 每天一点小知识

💧 深入了解 S p r i n g C l o u d A l i b a b a N a c o s :服务注册和配置中心 \color{#FF1493}{深入了解Spring Cloud Alibaba Nacos:服务注册和配置中心} 深入了解SpringCloudAlibabaNacos:服务注册和配置中心💧…

深入浅出解析LoRA完整核心基础知识 | 【算法兵器谱】

Rocky Ding 公众号:WeThinkIn 写在前面 【算法兵器谱】栏目专注分享AI行业中的前沿/经典/必备的模型&论文,并对具备划时代意义的模型&论文进行全方位系统的解析,比如Rocky之前出品的爆款文章Make YOLO Great Again系列。也欢迎大家提…

让Ai帮我们画个粽子,它会画成什么样呢?

让Ai帮我们画个粽子,它会画成什么样呢? 本文目录: 一、Ai绘图技术的现状 二、看看Ai理解的粽子是怎样的 2.1、基础粽子 2.2、生成不同风格的粽子 2.2.1、真实风格的粽子 2.2.2、插图风格的粽子 2.2.3、3D风格的粽子 2.2.4、卡通风格…

Mysql锁机制介绍

Mysql锁机制 锁是计算机协调多个进程或线程并发访问某一资源的机制。 在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&#xff0…

vue-cli笔记

vue的生命周期: 借鉴react 钩子函数: change() 挂载完毕,vue完成模板解析,并把初始的真实的dom元素放入到页面后执行 beforeCreate() {// 数据代理和数据监测创建之前console.log(beforeCreate) }, created() {console.l…

深度:全面解析数据智能的金融“炼金术”!

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 金融以其财富效应,成为最新科技的试金石。一项新技术出来后,人们首先闪过的念头就是“能不能用它赚钱”。例如,ChatGPT带火了大模型,人们也开始将目标聚焦到大模型在金融领域的…

【实战】 JWT、用户认证与异步请求(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(五)

文章目录 一、项目起航:项目初始化与配置二、React 与 Hook 应用:实现项目列表三、TS 应用:JS神助攻 - 强类型四、JWT、用户认证与异步请求1~56.用useAuth切换登录与非登录状态7.用fetch抽象通用HTTP请求方法,增强通用性8.用useHt…

AR宇航员互动体验软件:虚拟与现实叠加增强体验感

随着科技的不断发展,人们对太空探索的兴趣和热情也越来越高涨。为了满足人们对太空探索的渴望,广州华锐互动研发了宇航员AR模拟体验软件,这种软件可以让用户身临其境地体验太空探索的过程,提供一种全新的、令人兴奋的太空探索新体…

css基础知识十一:CSS3新增了哪些新特性?

一、是什么 css,即层叠样式表(Cascading Style Sheets)的简称,是一种标记语言,由浏览器解释执行用来使页面变得更为美观 css3是css的最新标准,是向后兼容的,CSS1/2的特性在CSS3 里都是可以使用…

图解CNN中的卷积(卷积运算、池化、Padding、多通道的卷积)

文章目录 卷积操作池化Padding对多通道(channels)图片的卷积套上激活函数是什么样的参考: 卷积层是深度学习神经网络中经常使用的一种层。它通过卷积运算来提取输入的特征,常用于图像、语音等信号处理任务中。 卷积层有以下几个参…

rocketmq-spring-boot-starter支持SpringBoot 1.x(spring-context 4.x)版本

1 问题说明 由于历史原因,项目使用的是SpringBoot1.x版本,而且由于种种原因,不能升级。在项目开发迭代过程中,决定使用RocketMQ作为消息中间件,因为是SpringBoot项目,理所应当的引入了rocketmq-spring-boo…

简单聊聊数字孪生与GIS融合的必要性

随着科技的不断发展和应用的不断深入,数字孪生和GIS在各自领域中展现出巨大的潜力。然而,更引人注目的是,数字孪生和GIS的融合将为许多行业带来全新的机遇和变革。在本文中,我们将探讨数字孪生和GIS融合的必要性,以及它…

2023ty计网期末综合题满分冲刺版

1. 假设有段1km长的CSMA/CD网络链路的数据传输率为1Gb/s。设信号在此链路媒介上的传播速度为2x105 km/s,求使用此协议的最短数据帧长度。 (1)传播时延:1/2000005微秒, (2)往返时延&#xff1a…

List合并的操作

List合并的操作 1.addAll方法 List list1new ArrayList();List list2new ArrayList();for (int i 0; i < 10; i) {list1.add(i*2);list2.add(i*21);}System.out.println(list1);//方法1&#xff1a;addAlllist1.addAll(list2);System.out.println(list1); 2.Stream操作 L…

ATTCK(二)之ATTCK的发展历史

ATT&CK的发展历史 MITRE公司 MITRE是美国NIST标准化组织选择的专注于网络安全的组织&#xff0c;由美国联邦政府资助。很多安全标准都MITRE制定的&#xff0c;比如有名的漏洞CVE编号规则以及威胁情报格式STIX。所以ATT&CK非常有影响力&#xff0c;而且未来能成为一个公…

MySQL----MHA高可用

文章目录 一、MHA理论1.1什么是 MHA1.2MHA 的组成1.3MHA 的特点 二、MHA的一主两从部署实验设计故障修复步骤&#xff1a; 一、MHA理论 1.1什么是 MHA MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出…

Java 日志重点梳理

大家好&#xff01;我是今越。重点梳理一下在 Java 程序开发中关于日志管理的知识点&#xff0c;以及在 Spring Boot 框架中该如何使用日志。 在 Java 中&#xff0c;日志框架主要分为两大类&#xff1a;日志门面和日志实现。 日志门面 日志门面定义了一组日志的接口规范&am…