Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • MySQL

    • 基础部分

      • 初识MySQL
      • 基础架构&日志
        • 查询语句
          • Server层
          • 存储引擎层
        • 更新语句
          • 🔥redo log(InnoDB引擎特有)
          • 🔥bin log(Server层)
          • 🔥执行流程
          • 🔥备份时间
        • 细节
          • 1.两阶段提交的合理性
          • 2.redo log与bin log功能
          • 2.1redo log
          • 2.2bin log
      • 事务隔离
      • 全局锁、表锁、行锁
      • 事务的隔离性和行锁
      • 索引
      • 索引深入(中)
      • 内存脏页刷盘
      • 数据库表的空间回收
      • count
      • order by
      • SQL语句性能差异分析
      • 幻读与间隙锁
      • 加锁规则案例分析
      • binlog和redolog如何写入磁盘
      • MySQL一致性与高可用性
      • kill命令
      • 全表扫描与内存占用
      • join
      • 临时表与内存表
      • 自增主键
      • insert操作加锁场景分析
      • grant
      • 分区表
      • 思维导图
    • 实战与处理方案

    • 面试

  • ORM框架

  • 数据库
  • MySQL
  • 基础部分
phan
2023-05-29
目录

基础架构&日志

# 基础架构&日志

# 查询语句

# Server层

  • 连接器

1.建立连接之后,就不能再修改权限;只能重新建立新的连接才能够生效。

2.只有释放连接之后才会真正释放资源,如果长时间占用长连接不释放MySQL内存,会导致OOM。因此需要定期断开长连接,程序里面可以判断执行过一个占用内存的大查询之后,断开连接。

  • 查询缓存

先前执行过的结果会以key-value的形式保存。key为查询语句,value为对应的查询结果。

⚠️⚠️⚠️一般不建议使用查询缓存,因为使用更新语句之后会清空所有表的缓存数据。对于热点数据而言,缓存命中率比较低。

  • 分析器

MySQL会对你的查询语句进行解析,具体分为两个步骤:

1.词法分析:从你的字符串语句当中识别出表名、字段名。

2.语法分析:判断输入的MySQL语句是否符合语法规则。语句会报错“You have an error in your SQL syntax”

  • 优化器

表中有多个索引时,优化器决定使用哪一个方案。

  • 执行器

执行前会先判断是否有查询权限,如果有权限则会调用InnoDB引擎接口执行查找语句,分为有无索引两种情况:

1.无索引的表:调用“获取表中这一行的数据”这一接口,然后判断是否符合where限制;循环调用“获取下一行数据”接口并执行先相同的判断逻辑。

2.有索引的表:调用“获取满足条件的第一行”这一接口,依次读取下一行。

# 存储引擎层

InnoDB、MyISAM、Memory(基于内存进行存储)

# 更新语句

设计理念:通过日志文件记录当前所有的操作,然后根据日志文件写入磁盘。降低了IO成本、查找成本,提升了效率,同时保存副本以应对写数据时数据库崩溃的问题,用于恢复数据。

WAL(Write-Ahead Logging)机制:预写日志。核心在于先写日志,再写磁盘。

更新语句会将对应数据表的查询缓存的所有数据删除,所有缓存失效。

# 🔥redo log(InnoDB引擎特有)

物理日志:记录的是在哪一个数据页做了什么修改。日志文件固定大小会使用完。因此所有操作记录写满之后需要清除空间。先写日志再写磁盘。

crash-safe:只要redo log写了新的数据,即使数据库异常重启,数据也能够根据redo log进行恢复。(binlog并没有该能力)

checkpoint:当前要擦除的位置

write pos:当前记录的位置

当write pos追上checkpoint之后,则说明当前当前日志已经写满了,因此checkpoint需要先擦掉一些记录之后才能继续执行新的更新。

# 🔥bin log(Server层)

逻辑日志:记录的相当于是SQL语句的原始逻辑内容。日志是追加写的,写完之后会自动切换到下一个。具有"归档"功能,而redo log并不能持久保存。

# 🔥执行流程

1.执行器首先拿到对应的数据(缓存或者是磁盘),并进行修改。

2.调用InnoDB引擎接口,将数据写入到内存,并且会将更新记录更新到redo log。

3.redo log完成后,InnoDB引擎会提醒执行器,随时可以提交事务。此时还处于prepare状态

4.执行器受到通知后,会生成该操作的bin log,并将日志写入磁盘。

5.执行器会调用InnoDB引擎的提交事务接口。将刚刚写入的redo log改成提交状态。

redo log两阶段提交:首先prepare和commit。目的是为了保证redolog和binlog两份文件逻辑一致。如果不采用两阶段提交,可能会存在两种情况:

  • 先redo log后bin log:crash之后,数据库能够恢复最新的数据。但是bin log中记载的还是旧数据。如果通过bin log将数据导入临时库,则该库和主数据库对比就没有最新的数据。
  • 先bin log后redo log:crash后,由于redo log没有写入最新的数据,因此恢复的数据库是旧数据。而通过bin log构建的临时库则是新数据。

因此,只要涉及到使用binlog搭建备用库(从库),恢复临时库,就会导致主从不一致的问题。两阶段提交是跨系统维持数据逻辑一致性时常用的一个方案。

# 🔥备份时间

一天一备份和一周一备份相比,”最长恢复时间“更短,也就是距离上一次可备份时间的时间间隔更短;但是因为一天一备的备份次数多,因此需要的存储空间也会更多。

从业务角度上看,一天一备更适用于那些被频繁修改的热点数据,这样需要通过备份数据恢复时,所使用的数据可以保证是最新的。

# 细节

# 1.两阶段提交的合理性

下图是两阶段提交发生崩溃的两个不同的时刻:

  • A时刻发生崩溃后,恢复时由于redo log处于prepare状态,同时bin log也没有写,因此事务会回滚。
  • B时刻发生崩溃后,虽然redo log仍处于prepare状态,但MySQL会验证bin log的完整性,如果是完整的则会提交事务。

换而言之,prepare阶段的redo log加上完整的bin log,重启后数据就能恢复。而之所以需要两阶段提交,是因为事务提交后就不能进行回滚,提交redo log后如果写bin log失败,那么就会无法回滚数据,出现不一致问题。

事实上两阶段提交是经典分布式问题,只有A确认自己“OK”了,那么B好了后才会提交。也就是确保双方的状态都是没问题的。

# 2.redo log与bin log功能

# 2.1redo log

核心作用是用于恢复数据。redo log因为是循环写,上面只会记录未刷盘的数据,经过刷盘持久化后的数据会从redo log删除。而bin log是追加写数据,无法判断上面哪些数据是刷盘后,哪些是没刷盘的。

当crash崩溃后,要想恢复已经写入日志但未刷盘的数据,bin log显然做不到;而对于redo log只需要将所有日志中的数据恢复到内存,并刷盘即可。这就是为什么redo log 具有crash safe的能力。具体包括以下几种情况:

  • 时刻A——change buffer写入,redo log buffer未提交,bin log未fsync到磁盘:崩溃后内存所有日志和数据丢失。

  • 时刻B——change buffer写入,redo log buffer 未提交,bin log已经fsync到磁盘:崩溃后通过bin log恢复redo log,然后再从redo log恢复change buffer。

  • redo log和bin log都已经持久化:崩溃后将磁盘旧的数据页读入内存,直接根据redo log恢复更新数据,最后将脏页落盘。

# 2.2bin log

作用一:归档,保留历史日志。

作用二:高可用方面,依赖于binlog复制进行备份数据库。

编辑 (opens new window)
#数据库
上次更新: 2023/12/15, 15:49:57
初识MySQL
事务隔离

← 初识MySQL 事务隔离→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式