笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 33-我查这么多数据,会不会把数据库内存打爆?

    • 全表扫描对 server 层的影响
      • 全表扫描对 InnoDB 的影响
        • 上一章答案
        EasT-Duan
        2024-03-30
        随笔
        目录

        33-我查这么多数据,会不会把数据库内存打爆?

        欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

        正文

        # 全表扫描对 server 层的影响

        查询出来的结果集不是把全部的结果集都加载出来,而是有个过程的。

        • 获取一行写入到 net_buffer 中,这块内存的大小是 net_buffer_length 定义的,默认为 16k。
        • 循环,直到 net_buffer 写满然后通过网络发送出去。
        • 发送成功后清空 net_buffer,继续读取。
        • 如果返回了 EAGAIN 或 WSAEWOULDBLOCK 那么就进入等待,直到网络栈可用再继续。

        也就是说 Mysql 是边读边发的,如果客户端接受的很慢,那么就容易阻塞服务端。通过 show processlist 命令查看如果是 Sending to client 这个状态就代表服务端的网络栈已经满了。

        上一章说的 -q 就是会读一行处理一行,如果说读取业务很复杂,速度很慢的话,服务端会很久才会取读取下一行。所以正常业务的话建议都使用 mysql_store_result 而不是 mysql_use_result 。

        注意

        mysql_store_result 和 边读边发 并不冲突,两者不是一个概念。

        • 边读边发面向的是 MySQL 的 server 端,首先会将数据先读取到 net_buffer 中,然后客户端来接受处理,如果客户端处理的速度很慢,net_buffer 就会慢然后进入等待状态。
        • mysql_store_result 面向的是服务端,服务端接受到数据后是直接处理还是存到本地,就是看着两个参数的配置。

        但是有时候通过查看 show processlist; 看到状态是 Sending data,而不是 Sending to client。

        • Sending data 状态通常表示 MySQL 服务器正在从存储引擎读取数据并发送给客户端。这个状态通常出现在执行查询操作时,比如 SELECT 语句。这个状态的持续时间取决于查询的复杂性和数据的大小。
        • Sending to client” 状态则表示 MySQL 服务器正在将查询结果发送给客户端。如果这个状态持续时间过长,可能是因为网络延迟,或者客户端处理数据的速度较慢。

        也就是说 Sending data 指的是服务端正在执行的查询的处理,而 Sending to client 指的是正在发送到客户端。

        # 全表扫描对 InnoDB 的影响

        InnoDB 通过 Buffer Pool 来保存更新和新增的结果,这块区域是从内存中分出来的,可以加速扫描的效率。一旦请求过来查询如果在 Buffer Pool 中没有从硬盘获取,如果有就直接从内存返回了。这里面存储的更新和新增结果总是最新的。

        但是 Buffer Pool 对于查询效果的加速有个依赖指标:内存命中率。

        show engine innodb status 通过这个命令中的 Buffer pool hit rate 字段可以看出来,一般情况下一个稳定的服务要达到 99%,而 100% 是很难达到的。

        InnoDB Buffer Pool 的大小是由参数 innodb_buffer_pool_size 确定的,这个值一般设置为物理内存的 6-8 成。

        InnoDB 的 LRU (最近最少使用 Least Recently Used, LRU) 算法。

        笔记

        这个算法的实现就是淘汰最久未使用的数据,它通过维护一个链表,每当访问了某个数据时,就将这个数据加入到链表的头部,如果数据本身存在于链表中,那么就将数据从链表的中间移动到链表的头部,这样最终下来,在链表尾部的数据一定就是最久未被使用的数据了,因此可以将其淘汰。

        但是 InnoDB 对这个算法进行了修改,分成了两个部分 young (从链头开始58\frac{5}{8}​8​​5​​) 和 old (从链尾开始38\frac{3}{8}​8​​3​​)。

        • 如果访问的元素在 young 区域,就和 LRU 的默认算法一致。
        • 新插入元素放在 old 区域中。
        • old 数据页中的数据每次被访问会有两个判断
          • 被访问的元素在 old 中存在时间是否超过了时间间隔,如果是就放在链表头部。
          • 如果没有超过时间间隔,就保持不变。
          • 时间间隔是由 innodb_old_blocks_time 参数控制的,单位为妙。

        # 上一章答案

        如果一个事务被 kill 之后,持续处于回滚状态,从恢复速度的角度看,你是应该重启等它执行结束,还是应该强行重启整个 MySQL 进程?

        • 这个问题需要考虑的是如果没有影响到系统的使用的话,比如在一个低峰期,还是等他自己完成回滚为好,毕竟重启服务可能会造成数据不一致。
        • 如果说影响到了其他业务的使用,需要做主备切换,让新的主库先提供服务,然后等他自己完成回滚。

        总的来说强制重启是一个下下策。

        #MySQL
        上次更新: 2025/04/12, 05:37:39
        最近更新
        01
        Reactor 核心
        02-24
        02
        前置条件
        10-30
        03
        计算机网络
        09-13
        更多文章>
        Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式