《MySQL45讲》读书笔记

重建表

alter table t engine = InnoDB(也就是recreate),而optimize table t 等于recreate+analyze,让表大小变小

重建表的执行流程

  • 建立一个临时文件,扫描表 t 主键的所有数据页;
  • 用数据页中表 t 的记录生成 B+ 树,存储到临时文件中;
  • 生成临时文件的过程中,将所有对 t 的操作记录在一个日志文件(row log)中;
  • 临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表 t相同的数据文件;
  • 用临时文件替换表 t 的数据文件。

注意:在重建表的时候, InnoDB不会把整张表占满, 每个页留了1/16给后续的更新用。 也就是说, 其实重建表之后不是“最”紧凑的。

Online DDL

ALTER TABLE tbl_name ADD COLUMN col_name col_type, ALGORITHM=INPLACE, LOCK=NONE;

LOCK选项

  • SHARE:共享锁,执行DDL的表可以读,但是不可以写。
  • NONE:没有任何限制,执行DDL的表可读可写。
  • EXCLUSIVE:排它锁,执行DDL的表不可以读,也不可以写。
  • DEFAULT:默认值,也就是在DDL语句中不指定LOCK子句的时候使用的默认值。如果指定LOCK的值为DEFAULT,那就是交给MySQL子句去觉得锁还是不锁表。不建议使用,如果你确定你的DDL语句不会锁表,你可以不指定lock或者指定它的值为default,否则建议指定它的锁类型。
准备:
1、对表加元数据共享升级锁,并升级为排他锁;(此时DML不能并行)
2、判断使用inplace算法
3、判断语句是“rebuild table” 还是 “no-rebuild”,rebuild 在原表所在的路径下创建.frm和.ibd临时中转文件;
【在引擎层克隆,而不是像copy那样,在server层创建(create like)】

注意:加列的操作是需要rebuild table的
【rebuild table】---生成中转文件表


++++
no-rebuild的情况:
除创建二级索引外只创建.frm文件,其中添加二级索引操作最为特殊,该操作属于no-rebuild不会生成.ibd,
但实际上对.ibd文件却做了修改,该操作会在参数tmpdir指定路径下生成临时文件,用于存储索引排序结果,然后再合并到.ibd文件中
++++
4、申请row log空间,用于存放DDL执行阶段产生的DML操作。(no-rebuild不需要)【在innodb_sort_buffer块中】


执行:(online)
1、释放排他锁,保留元数据共享升级锁;(此时DML可以并行)
2、扫描原表主键以及二级索引的所有数据页,生成 B+ 树,存储到临时文件中;【在引擎层扫描,最耗时】
3、将所有对原表的DML操作记录在日志文件row log中,并回放部分row_log。

提交阶段:
1、升级元数据共享升级锁,产生排他锁锁表;(此时DML不能并行了)
2、重做row log中的内容;(no-rebuild不需要)
3、重命名原表文件,将临时文件改名为原表文件名,删除原表文件;
4、提交事务,变更完成。


在 InnoDB 引擎中 count(*)、count(1)、count(主键)、count(字段) 哪个性能最高?

count(字段)<count(主键 id)<count(1)≈count(*) 题目解析:

  • 对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。
  • 对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
  • 对于 count(字段) 来说,如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再判断一下,不是 null 才累加。
  • 对于 count(*) 来说,并不会把全部字段取出来,而是专门做了优化,不取值,直接按行累加。

所以最后得出的结果是:count(字段)<count(主键 id)<count(1)≈count(*)。

–single-transaction逻辑备份

当mysqldump使用参数–single-transaction的时候, 导数据之前就会启动一个事务, 来确保拿到一致性视图。

single-transaction方法只适用于所有的表使用事务引擎的库。 如果有的表使用了不支持事务的引擎, 那么备份就只能通过FTWRL(全局锁)方法。

这往往是DBA要求业务开发人员使用InnoDB替代MyISAM的原因之一。

当备库用–single-transaction做逻辑备份的时候, 如果从主库的binlog传来一个DDL语句会怎么样?

Q1:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Q2:START TRANSACTION WITH CONSISTENT SNAPSHOT;
/* other tables */
Q3:SAVEPOINT sp;
/* 时刻 1 */
Q4:show create table `t1`;
/* 时刻 2 */
Q5:SELECT * FROM `t1`;
/* 时刻 3 */
Q6:ROLLBACK TO SAVEPOINT sp;
/* 时刻 4 */
/* other tables */

1. 如果在Q4语句执行之前到达, 现象: 没有影响, 备份拿到的是DDL后的表结构。

2. 如果在“时刻 2”到达, 则表结构被改过, Q5执行的时候, 报 Table definition has changed,please retrytransaction, 现象: mysqldump终止;

3. 如果在“时刻2”和“时刻3”之间到达, mysqldump占着t1的MDL读锁, binlog被阻塞, 现象:主从延迟, 直到Q6执行完成。

4. 从“时刻4”开始, mysqldump释放了MDL读锁, 现象: 没有影响, 备份拿到的是DDL前的表结构。

删除一个表里面的前10000行数据

要删除一个表里面的前10000行数据, 有以下三种方法可以做到:

第一种, 直接执行delete from Tlimit 10000;

第二种, 在一个连接中循环执行20次 delete from Tlimit 500;

第三种, 在20个连接中同时执行delete from Tlimit 500。

分析:

第一种方式(即: 直接执行delete from Tlimit 10000) 里面, 单个语句占用时间长, 锁的时间也比较长; 而且大事务还会导致主从延迟。

第二种方式是相对较好的。

第三种方式(即: 在20个连接中同时执行delete from Tlimit 500) , 会人为造成锁冲突。

change buffer

当需要更新一个数据页时, 如果数据页在内存中就直接更新, 而如果这个数据页还没有在内存中的话, 在不影响数据一致性的前提下, InooDB会将这些更新操作缓存在change buffer中, 这样就不需要从磁盘中读入这个数据页了。 在下次查询需要访问这个数据页的时候, 将数据页读入内存, 然后执行change buffer中与这个页有关的操作。 通过这种方式就能保证这个数据逻辑的正确性。将change buffer中的操作应用到原数据页, 得到最新结果的过程称为merge。 除了访问这个数据页会触发merge外, 系统有后台线程会定期merge。 在数据库正常关闭(shutdown) 的过程中,也会执行merge操作。对于唯一索引来说, 所有的更新操作都要先判断这个操作是否违反唯一性约束。 比如, 要插入(4,400)这个记录, 就要先判断现在表中是否已经存在k=4的记录, 而这必须要将数据页读入内存才能判断。 如果都已经读入到内存了, 那直接更新内存会更快, 就没必要使用change buffer了。

因此, 唯一索引的更新就不能使用change buffer, 实际上也只有普通索引可以使用。change buffer用的是buffer pool里的内存, 因此不能无限增大。 change buffer的大小, 可以通

过参数innodb_change_buffer_max_size来动态设置。 这个参数设置为50的时候, 表示changebuffer的大小最多只能占用buffer pool的50%。将数据从磁盘读入内存涉及随机IO的访问, 是数据库里面成本最高的操作之一。 change buffer因为减少了随机磁盘访问, 所以对更新性能的提升是会很明显的。

merge的执行流程是这样的:

1. 从磁盘读入数据页到内存(老版本的数据页) ;

2. 从change buffer里找出这个数据页的change buffer 记录(可能有多个) , 依次应用, 得到新版数据页;

3. 写redo log。 这个redo log包含了数据的变更和change buffer的变更。

redo log 主要节省的是随机写磁盘的IO消耗( 转成顺序写) , 而change buffer主要节省的则是随机读磁盘的IO消耗。

字符集不同连表查询用不上索引

performance_schema库优化

MySQL 5.6版本以后提供的performance_schema库, 就在file_summary_by_event_name

表里统计了每次IO请求的时间

Buffer Pool

Buffer Pool对查询的加速效果, 依赖于一个重要的指标, 即: 内存命中率。

你可以在show engine innodb status结果中, 查看一个系统当前的BP命中率。 一般情况下, 一个稳定服务的线上系统, 要保证响应时间符合要求的话, 内存命中率要在99%以上。

执行show engine innodb status , 可以看到“Buffer pool hit rate”字样, 显示的就是当前的命中率。

InnoDB Buffer Pool的大小是由参数 innodb_buffer_pool_size确定的, 一般建议设置成可用物理内存的60%~80%。

所以, innodb_buffer_pool_size小于磁盘的数据量是很常见的。 如果一个 Buffer Pool满了, 而又要从磁盘读入一个数据页, 那肯定是要淘汰一个旧数据页的。

InnoDB管理Buffer Pool的LRU算法, 是用链表来实现的。

1. 在图的状态1里, 链表头部是P1, 表示P1是最近刚刚被访问过的数据页; 假设内存里只能放下这么多数据页;

2. 这时候有一个读请求访问P3, 因此变成状态2, P3被移到最前面;

3. 状态3表示, 这次访问的数据页是不存在于链表中的, 所以需要在Buffer Pool中新申请一个

数据页Px, 加到链表头部。 但是由于内存已经满了, 不能申请新的内存。 于是, 会清空链表

末尾Pm这个数据页的内存, 存入Px的内容, 然后放到链表头部。

4. 从效果上看, 就是最久没有被访问的数据页Pm, 被淘汰了。

实际上, InnoDB对LRU算法做了改进

在InnoDB实现上, 按照5:3的比例把整个LRU链表分成了young区域和old区域。 图中LRU_old指向的就是old区域的第一个位置, 是整个链表的5/8处。 也就是说, 靠近链表头部的5/8是young区域, 靠近链表尾部的3/8是old区域。改进后的LRU算法执行流程变成了下面这样。

1. 图7中状态1, 要访问数据页P3, 由于P3在young区域, 因此和优化前的LRU算法一样, 将其移到链表头部, 变成状态2。

2. 之后要访问一个新的不存在于当前链表的数据页, 这时候依然是淘汰掉数据页Pm, 但是新插入的数据页Px, 是放在LRU_old处。

3. 处于old区域的数据页, 每次被访问的时候都要做下面这个判断:

若这个数据页在LRU链表中存在的时间超过了1秒, 就把它移动到链表头部;

如果这个数据页在LRU链表中存在的时间短于1秒, 位置保持不变。 1秒这个时间, 是由参数innodb_old_blocks_time控制的。 其默认值是1000, 单位毫秒。

MySQL采用的是边算边发的逻辑, 因此对于数据量很大的查询结果来说, 不会在server端保存完整的结果集。 所以, 如果客户端读结果不及时, 会堵住MySQL的查询过程, 但是不会把内

存打爆。而对于InnoDB引擎内部, 由于有淘汰策略, 大查询也不会导致内存暴涨。 并且, 由于InnoDB对LRU算法做了改进, 冷数据的全表扫描, 对Buffer Pool的影响也能做到可控。

InnoDB对Bufffer Pool的LRU算法做了优化,

即: 第一次从磁盘读入内存的数据页, 会先放在old区域。 如果1秒之后这个数据页不再被访问了, 就不会被移动到LRU链表头部, 这样对Buffer Pool的命中率影响就不大。

但是, 如果一个使用BNL算法的join语句(无索引join,参考https://www.cnblogs.com/booksea/p/17380941.html), 多次扫描一个冷表, 而且这个语句执行时间超过1秒,就会在再次扫描冷表的时候, 把冷表的数据页移到LRU链表头部。

这种情况对应的, 是冷表的数据量小于整个Buffer Pool的3/8, 能够完全放入old区域的情况。如果这个冷表很大, 就会出现另外一种情况: 业务正常访问的数据页, 没有机会进入young区

域。由于优化机制的存在, 一个正常访问的数据页, 要进入young区域, 需要隔1秒后再次被访问到。 但是, 由于我们的join语句在循环读磁盘和淘汰内存页, 进入old区域的数据页, 很可能在1秒之内就被淘汰了。 这样, 就会导致这个MySQL实例的Buffer Pool在这段时间内, young区域的数据页没有被合理地淘汰。也就是说, 这两种情况都会影响Buffer Pool的正常运作。

大表join操作虽然对IO有影响, 但是在语句执行结束后, 对IO的影响也就结束了。 但是,对Buffer Pool的影响就是持续性的, 需要依靠后续的查询请求慢慢恢复内存命中率。

判断要不要使用join语句时, 就是看explain结果里面, Extra字段里面有没有出现“BlockNested Loop”字样。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为机考入门python3--(22)牛客22- 汽水瓶

分类&#xff1a;数字 知识点&#xff1a; 整除符号// 5//3 1 取余符号% 5%3 2 题目来自【牛客】 import sysdef calc_soda_bottles(n):if n 0: # 结束输入&#xff0c;不进行处理returnelse:# 循环进行汽水换算total_drunk 0 # 记录总共喝了多少瓶汽水while…

XSS注入漏洞解析(上)

XSS跨站脚本介绍 跨站脚本&#xff08;Cross-Site Scripting&#xff0c;XSS/CSS&#xff09;是一种经常出现在Web应用程序中的计算机安全漏洞&#xff0c;是 由于Web应用程序对用户的输入过滤不足而产生的。攻击者利用网站漏洞把恶意的脚本代码&#xff08;通常包括 HTML代码和…

深入浅出 BERT

Transformer 用于学习句子中的长距离依赖关系&#xff0c;同时执行序列到序列的建模。 它通过解决可变长度输入、并行化、梯度消失或爆炸、数据规模巨大等问题&#xff0c;比其他模型表现更好。使用的注意力机制是神经架构的一部分&#xff0c;使其能够动态突出显示输入数据的…

Meta Llama 3 使用 Hugging Face 和 PyTorch 优化 CPU 推理

原文地址&#xff1a;meta-llama-3-optimized-cpu-inference-with-hugging-face-and-pytorch 了解在 CPU 上部署 Meta* Llama 3 时如何减少模型延迟 2024 年 4 月 19 日 万众期待的 Meta 第三代 Llama 发布了&#xff0c;我想确保你知道如何以最佳方式部署这个最先进的&…

java基于云计算的SaaS医院his信息系统源码 HIS云平台源码

目录 云HIS功能模块 1、预约挂号&#xff1a; 2、药库管理&#xff1a; 3、门诊医生站&#xff1a; 4、门诊费用&#xff1a; 5、药房管理&#xff1a; 6、治疗室&#xff08;门诊护士工作站&#xff09;&#xff1a; 7、统计分析&#xff1a; 8、财务管理&#xff1a;…

vue快速入门(五十三)使用js进行路由跳转

注释很详细&#xff0c;直接上代码 上一篇 新增内容 几种常用的路由跳转方式演示 源码 App.vue <template><div id"app"><div class"nav"><!-- router-link 自带两个高亮样式类 router-link-exact-active和router-link-active区别&a…

《QT实用小工具·五十四》果冻弹出效果的动画按钮

1、概述 源码放在文章末尾 该项目实现动画按钮&#xff0c;鼠标放在按钮上可以弹性拉出的三个按钮&#xff0c;使用贝塞尔曲线实现&#xff0c;项目demo显示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef WATERCIRCLEBUTTON_H #define WATERCIRCLEBUTTON…

MySQL CRUD进阶

前言&#x1f440;~ 上一章我们介绍了CRUD的一些基础操作&#xff0c;关于如何在表里进行增加记录、查询记录、修改记录以及删除记录的一些基础操作&#xff0c;今天我们学习CRUD&#xff08;增删改查&#xff09;进阶操作 如果各位对文章的内容感兴趣的话&#xff0c;请点点小…

mac查看Linux服务器的性能

mac上安装 linux系统 如果有 linux服务器账号密码&#xff0c;那么上一部可忽略&#xff1b; 比如&#xff1a;直接连接阿里云或腾讯云账号 1. 安装termius 链接: https://pan.baidu.com/s/1iYsZPZThPizxqtkLPT89-Q?pwdbw6j 提取码: bw6j 官网 Termius - SSH platform for …

[Linux][网络][TCP][一][TCP基础][TCP报头]详细讲解

目录 1.TCP头部格式2.TCP协议的特点3.TCP如何封装与分用4.通过序列号和确认应答号提高可靠性1.32位序列号2.32位确认应答号3.保证可靠性4.为什么序列号和确认应答号是单独的字段 5.窗口大小1.TCP的发送和接收缓冲区2.窗口大小 6.连接管理机制 1.TCP头部格式 TCP全称为"传输…

C语言数据结构之队列

目录 1.队列的概念及结构2.队列的实现逻辑3.队列的代码实现4.相关例题选择题 •͈ᴗ•͈ 个人主页&#xff1a;御翮 •͈ᴗ•͈ 个人专栏&#xff1a;C语言数据结构 •͈ᴗ•͈ 欢迎大家关注和订阅!!! 1.队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#x…

SpringBoot与SpringMVC的区别

SpringBoot与SpringMVC的区别是什么&#xff1f; SpringBoot和SpringMVC是Java开发中常用的两个框架&#xff0c;它们都是由Spring框架所提供的&#xff0c;但在功能和使用方式上有着一些区别。本文将分别介绍SpringBoot和SpringMVC的特点和区别。 一、SpringBoot的特点&#…

第16章 基于结构的测试技术(白盒测试技术)

一、静态测试技术 &#xff08;一&#xff09;概述 不运行程序代码的情况下&#xff0c;通过质量准则或其他准则对测试项目进行检查的测试类型&#xff0c;人工或工具检查。 1、代码检查 2、编码规则检查 软件编码规范评测&#xff1a;源程序文档化、数据说明、语句结构、…

wpf线程中更新UI的4种方式

在wpf中&#xff0c;更新UI上面的数据&#xff0c;那是必经之路&#xff0c;搞不好&#xff0c;就是死锁&#xff0c;或者没反应&#xff0c;很多时候&#xff0c;都是嵌套的非常深导致的。但是更新UI的方式&#xff0c;有很多的种&#xff0c;不同的方式&#xff0c;表示的意思…

01-MySQL 基础篇笔记

一、MySQL 概述 1.1 数据库相关概念 数据库&#xff1a;&#xff08;DB&#xff1a;DataBase&#xff09; 存储数据的仓库&#xff0c;数据是有组织的进行存储 数据库管理系统&#xff1a;&#xff08;DBMS&#xff1a;DataBase Management System&#xff09; 操作和管理数…

论文阅读笔记(AAAI 20)Order Matters

个人博客地址 注&#xff1a;部分内容参考自GPT生成的内容 论文笔记&#xff1a;Order Matters&#xff08;AAAI 20&#xff09; 用于二进制代码相似性检测的语义感知神经网络 论文:《Order Matters: Semantic-Aware Neural Networks for Binary Code Similarity Detection》…

时间日志格式的统一和定制

返回当前格式的时间没有错误&#xff0c;但是不符合中国人的阅读习惯 解决&#xff1a; 方案一&#xff1a;JsonFormat 解决后端 传到 前端格式问题 依赖&#xff1a; <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jack…

基于MQTT通信开发的失物招领小程序

项目架构设计 这个项目采用前后端分离的方式&#xff0c;重新设计了两条链路来支撑程序的信息获取和传递 前端的小程序页面再启动页面渲染时&#xff0c;直接通过DBAPI从后端数据库获取信息&#xff0c;直接渲染在小程序中项目中给DBAPI的定位是快速从后端获取信息&#xff0…

C语言 计数控制循环

今天 我们来说 计数控制的循环 对于循环次数 我们已知的循环 我们称之为 计数控制的循环 这种情况 我们一般选择 for来实现 更为方便 先看一个案例 求 1 到 N 的累加合 我们代码可以这样写 #define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告 #pragma warning(disable:6031…

一键自动化博客发布工具,chrome和firfox详细配置

blog-auto-publishing-tools博客自动发布工具现在已经可以同时支持chrome和firefox了。 很多小伙伴可能对于如何进行配置和启动不是很了解&#xff0c;今天带给大家一个详细的保姆教程&#xff0c;只需要跟着我的步骤一步来就可以无障碍启动了。 前提条件 前提条件当然是先下…