MySQL存储管理(一):删数据

从表中删除数据


从表中删除数据,也即是delete过程。

什么是表空间

表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。默认情况下,InnoDB存储引擎有一个共享表空间idbdata1,即所有数据都存放在这个表空间内。如果用户启用了参数 innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。

如果启用了 innodb_file_per_table 参数,需要注意的是每张表的表空间内存放的只是数据、索引和插入缓冲Bitmap页,其他类的数据,如回滚(undo)信息,插入缓冲索引页、系统事务信息,二次写缓冲(Double write buffer)等还是存放在原来的共享表空间内。这同时也说明了另一个问题,即使在启用了参数 innodb_file_per_table 之后,共享表空间还是会不断地增加其大小。

表数据存放

一个InnoDB表包含两部分, 即: 表结构定义和数据。

表结构定义

在MySQL 8.0版本以前, 表结构是存在以.frm为后缀的文件里。

从MySQL 8.0版本开始, 则已经允许把表结构定义放在系统数据表中了。 表结构定义占用的空间很小。

表数据

表数据既可以存在共享表空间里, 也可以是单独的文件。 这个行为是由参数innodb_file_per_table控制的:

  • 这个参数设置为OFF表示的是, 表的数据放在系统共享表空间, 也就是跟数据字典放在一起。
  • 这个参数设置为ON表示的是, 每个InnoDB表数据存储在一个以 .ibd为后缀的文件中。

从MySQL 5.6.6版本开始, 它的默认值就是ON了。

规范:建议你不论使用MySQL的哪个版本, 都将这个值设置为ON。 因为, 一个表单独存储为一个文件更容易管理, 而且在你不需要这个表的时候, 通过drop table命令, 系统就会直接删除这个文件。 而如果是放在共享表空间中, 即使表删掉了, 空间也是不会回收的。

清理表数据的方式有以下几种:

1)drop table:删除整个表,回收表空间;若表数据独立存放,则直接删除对应.ibd文件。

2)delete from table:只是把记录/数据页标记为“可复用”,但磁盘文件的大小是不会变。

3)truncate table:相当于drop+create。

数据删除流程

问1:使用delete删除表中的记录时,表空间没有被回收,为什么?

数据页存放在文件中,假设数据页中的一些记录被使用delete删除了,这时数据页并不会真正的删除这些记录,而是把这些记录标记为删除,即被标记删除的位置可以被复用。如果数据页上的所有记录都被删除了,则可以复用整个数据页。但是磁盘上,文件不会变小。

问2:记录的复用和数据页的复用有什么区别?

假设要删掉记录R4,InnoDB引擎只会把R4记录标记为删除。如果之后要再插入一个ID在300和600之间的记录时,可能会复用这个位置。但如果插入的是一个ID是800的行, 就不能复用这个位置了。

而当整个数据页中的记录都被删除时(整个页从B+树里面摘掉),可以复用到任何位置。 以下图为例, 如果将数据页page A上的所有记录删除以后, page A会被标记为可复用。 这时候如果要插入一条ID=50的记录需要使用新页的时候, page A是可以被复用的。

如果相邻的两个数据页利用率都很小, 系统就会把这两个页上的数据合到其中一个页上, 另外一个数据页就被标记为可复用。

执行delete命令后,这些可以复用,而没有被使用的空间,看起来就像是”空洞“。

实际上, 不止是删除数据会造成空洞, 插入数据、更新数据也会。

1)插入数据造成空洞

如果数据是按照索引递增顺序插入的, 那么索引是紧凑的。 但如果数据是随机插入的, 就可能造成索引的数据页分裂。假设下图中page A已经满了, 这时我要再插入一行数据, 会怎样呢?

可以看到, 由于page A满了, 再插入一个ID是550的数据时, 就不得不再申请一个新的页面page B来保存数据了。 页分裂完成后, page A的末尾就留下了空洞(注意: 实际上, 可能不止1个记录的位置是空洞) 。

2)更新数据造成空洞

更新索引上的值, 可以理解为删除一个旧的值, 再插入一个新值。 不难理解, 这也是会造成空洞的。

问:如何去掉这些空洞?

也就是说, 经过大量增删改的表, 都是可能存在空洞的。 所以, 如果能够把这些空洞去掉, 就能达到收缩表空间的目的。

而重建表,就可以达到这样的目的。

重建表

重建表的意义在于回收表空间,使得表的存储结构更加紧凑;

那么表又是如何重建的呢?

假设有一个表A,需要做空间收缩,把表中存在的空洞去掉,具体过程如下:

1)新建一个与表A结构相同的表B;

2)按照主键ID递增的顺序,把数据一行一行地从表A里读出来再插入到表B中;

3)把表B作为临时表, 数据从表A导入表B的操作完成后, 用表B替换A, 从效果上看, 就起到了收缩表A空间的作用。

MySQL可以使用如下命令重建表:

alter table A engine=InnoDB;

MySQL5.6之前版本重建表示意图:

显然, 花时间最多的步骤是往临时表插入数据的过程, 如果在这个过程中, 有新的数据要写入到表A的话, 就会造成数据丢失。 因此, 在整个DDL过程中, 表A中不能有更新。 也就是说, 这个DDL不是Online的。(MySQL5.6之前版本)

在MySQL 5.6版本开始引入的Online DDL, 对这个操作流程做了优化。引入了Online DDL之后, 重建表的流程:

1)建立一个临时文件,扫描表A主键的所有数据页;

2)用数据页中表A的记录生成B+树,存储到临时文件中;

3)生成临时文件的过程中,将所有对A的操作记录在一个日志文件(row log)中,对应的是图中state2的状态;

4)临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表A相同的数据文件,对应的就是图中state3的状态;

5)用临时文件替换表A的数据文件;

MySQL5.6之后版本重建表示意图:

由于日志文件的存在,允许对表A做增删改操作。 这也就是Online DDL名字的来源,所谓Online,即对表进行DDL操作的同时,允许对该表进行增删改操作(DML)。

Online DDL过程需要加MDL锁(元数据锁),过程如下:

1)拿MDL写锁;

2)降级成MDL读锁;

3)真正做DDL;

4)升级成MDL写锁;

5)释放MDL锁;

之所以加写锁,是为了等待加读锁的DDL或DML完成;退化为读锁,是为了不阻塞DML语句的执行;

注1:

  • mysql
  • mysql >= 5.6,改进重建表过程,允许Online DDL。

注2:重建表的过程最耗时的是拷贝数据,因而该过程中允许DML,将会获得比较多的收益;这也是Online DDL的意义;

注3:对于大表进行重建表的操作消耗较大的CPU和IO,因而需要考虑在业务不繁忙的情况下进行;为保证安全,可以使用gh-ost工具;

Copy和Inplace

copy和inplace是重建表的两种策略,重建表默认使用的是inplace。

可以通过如下命令显示指定重建表的策略:

alter table t engine=innodb, ALGORITHM = inplace;
alter table t engine=innodb, ALGORITHM = copy;

问1:copy和inplace有什么区别?

1)copy的含义:当使用ALGORITHM=copy的时候, 表示的是强制拷贝表, 对应的流程就是上一小节第一张图的操作过程。

2)inlace的含义:在上一小节第二张图中,把表A重建出来的数据存放在“tmp_file”里的, 这个临时文件是InnoDB在内部创建出来的。 整个过程都是在InnoDB内部完成。对于server层来说, 没有把数据挪动到临时表, 是一个“原地”操作, 这就是“inplace”名称的来源。所谓inplace,是索引创建在原表上直接进行,而表数据依然需要数据拷贝;区别在于:

  • 拷贝过程不记录undo log和redo log;
  • 二级索引是有序的,可以按顺序加载;
  • 无需Change Buffer,因为对于二级索引没有随机写操作;

问2:如果你有一个1TB的表, 现在磁盘间是1.2TB, 能不能做一个inplace的DDL呢?

答:不能。

因为, tmp_file也是要占用临时空间的。我们重建表的这个语句alter table t engine=InnoDB, 其实隐含的意思是:

-- 重建表
alter table t engine=innodb, ALGORITHM=inplace;

问3:inplace跟Online是不是就是一个意思?

答:不是。只是在重建表这个逻辑中刚好是这样而已。

比如, 如果我要给InnoDB表的一个字段加全文索引, 写法是:

alter table t add FULLTEXT(field_name);

这个过程是inplace的, 但会阻塞增删改操作, 是非Online的。

如果说这两个逻辑之间的关系是什么的话, 可以概括为:

  • DDL过程如果是Online的, 就一定是inplace的;
  • 反过来未必, 也就是说inplace的DDL, 有可能不是Online的。 截止到MySQL 8.0, 添加全文索引(FULLTEXTindex) 和空间索引(SPATIAL index)就属于这种情况。

问4:使用optimize table、 analyze table和alter table这三种方式重建表有什么区别?

1)从MySQL 5.6版本开始, alter table t engine = InnoDB(也就是recreate) 默认的就是上一小节第二张图的流程了。

2)analyze table t 其实不是重建表, 只是对表的索引信息做重新统计, 没有修改数据, 这个过程中加了MDL读锁。

3)optimize table t 等于recreate+analyze。

问5:假设现在有人碰到了一个“想要收缩表空间,结果适得其反”的情况,看上去是这样的:

一个表t文件大小为1TB;

对这个表执行 alter table t engine=InnoDB;

发现执行完成后,空间不仅没变小,还稍微大了一点儿,比如变成了1.01TB。

你觉得可能是什么原因呢 ?

答:

1)这个表本身就已经没有空洞了,比如刚做过一次重建表操作。且在重建表的时候,InnoDB不会把整张表占满,每个页留了1/16给后续的更新用,所以重建之后,文件就反而变大了。

2)重建过程中,存在DML执行,因而在row log重新应用时,又产生了空洞。

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

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

相关文章

20.Cargo和Crates.io

标题 一、采用发布配置自定义构建1.1 默认配置1.2 修改配置项 二、将crate发布到Crates.io2.1 编写文档注释2.2 常用(文档注释)部分2.3 文档注释作用测试2.4 为包含注释的项添加文档注释2.5 使用pub use导出公有API2.6 创建Crates.io账号2.7 发布2.8 版本…

基于STM8系列单片机驱动LCD12864液晶程序

1)单片机/ARM硬件设计小知识,分享给将要学习或者正在学习单片机/ARM开发的同学。 2)内容属于原创,若转载,请说明出处。 3)提供相关问题有偿答疑和支持。 LCD12864支持串行和并行的通信传输方式&#xff…

NeRF从入门到放弃3: EmerNeRF

https://github.com/NVlabs/EmerNeRF 该方法是Nvidia提出的,其亮点是不需要额外的2D、3Dbox先验,可以自动解耦动静field。 核心思想: 1. 动、静filed都用hash grid编码,动态filed比静态多了时间t,静态的hash编码输入是…

C语言笔试题:实现把一个无符号整型数字的二进制序列反序后输出

目录 题目 实例 方法一:直接交换 方法二:间接交换 拓展 题目 编写一个函数,将一个无符号整数的所有位逆序(在32位机器下) 实例 例如有一个无符号整数 unsigned int num 32; unsigned int 在32位系统中占4个字…

如何选择优质智慧公厕系统厂家?@光明源

随着智慧城市建设的推进,智慧公厕系统成为提升城市公共服务水平的重要一环。选择一家优质的智慧公厕系统厂家不仅能确保设备的先进性和可靠性,还能提升用户体验和管理效率。以下是选择优质智慧公厕系统厂家的关键要素。 1. 厂家资质和信誉 1.1 资质认证…

VS C++常用错误与解决方法

无法找到 v143 的生成工具(平台工具集 “v143”) 若要使用 v143 生成工具进行生成,请安装 v143 生成工具。或者,可以升级到当前 Visual Studio 工具,方式是通过选择“项目”菜单或右键单击该解决方案,然后选择“重定解决方案目标…

外星人Alienware m18R1 原厂Windows11系统

装后恢复到您开箱的体验界面,包括所有原机所有驱动AWCC、Mydell、office、mcafee等所有预装软件。 最适合您电脑的系统,经厂家手调试最佳状态,性能与功耗直接拉满,体验最原汁原味的系统。 原厂系统下载网址:http://w…

绝对值不等式——AcWing 104. 货仓选址

绝对值不等式 定义 与数学中的绝对值不等式定义一致,即含有绝对值符号的不等式。 运用情况 在一些需要根据数值与特定值的距离关系来进行判断和处理的算法中。用于对数据范围进行约束和界定。 注意事项 确保对绝对值的处理正确,尤其是在复杂的逻辑…

基于chatgpt-on-wechat搭建个人知识库微信群聊机器人

前言 啊,最近在别人微信群里看到一个聊天机器人,感觉挺好玩的。之前GPT刚出来的时候就知道有人把聊天机器人接入到微信或者QQ中来增加互动,但是当时没想那个想法。 很久没关注这块了,发现现在可以使用大模型知识库的方式来打造自…

【面试干货】Hashtable 与 HashMap 的区别

【面试干货】Hashtable 与 HashMap 的区别 1、线程安全性2、对null值的处理3、遍历方式4、遍历示例5、总结 💖The Begin💖点点关注,收藏不迷路💖 在Java中,Hashtable和HashMap都是基于哈希表实现的Map接口。然而&#…

[Django学习]前端+后端两种方式处理图片流数据

方式1:数据库存放图片地址,图片存放在Django项目文件中 1.首先,我们现在models.py文件中定义模型来存放该图片数据,前端传来的数据都会存放在Django项目文件里的images文件夹下 from django.db import modelsclass Image(models.Model):title models.C…

Windows10任务栏卡顿解决方案

一、重新启动任务资源管理器 右键底部任务栏选择“任务管理器”;按快捷键“CtrlShiftEsc”;搜索框搜索“任务管理器”并单击“打开”;“WinX”打开开始菜单附属菜单,在列表中选择“任务管理器” ;按下“ctrlaltdelete”…

24年安克创新社招入职自适应能力cata测评真题分享北森测评高频题库

第一部分:安克创新自适应能力cata测评 感谢您关注安克创新社会招聘,期待与您一起弘扬中国智造之美。 为对您做出全面的评估,现诚邀您参加我们的在线测评。 测评名称:社招-安克创新自适应能力cata测评 第二部分:安克…

容器之笔记本构件演示

代码&#xff1a; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>void rotate_book(GtkButton *button, GtkNotebook *notebook) {gtk_notebook_set_tab_pos(notebook, (notebook…

Linux驱动开发(三)--新字符设备驱动开发 LED驱动开发升级

1、新字符设备驱动原理 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可&#xff0c;但是这样会 带来两个问题 需要我们事先确定好哪些主设备号没有使用 会将一个主设备号下的所有次设备号都使用掉&#xff0c;比如现在设置 LED 这个主设备号为200&…

这周,接连两位程序员猝死...

这周接连发生了两起不幸的事。俩位程序员去世的消息&#xff0c;深感悲伤和惋惜。 6月17号下午&#xff0c;一位负责研发的女员工在虾皮研发中心办公室猝死&#xff0c;年仅 30 岁。 官方通告&#xff1a; 同一天&#xff0c;另一位科大讯飞的高级测试工程师在家突发不适离世…

UDS服务——TransferData (0x36)

诊断协议那些事儿 诊断协议那些事儿专栏系列文章,本文介绍TransferData (0x36)—— 数据传输,用于下载/上传数据时用的,数据的传输方向由不同的服务控制:0x34服务表示下载,0x35服务表示上传。通过阅读本文,希望能对你有所帮助。 文章目录 诊断协议那些事儿传输数据服务…

Xshell7免费版下载安装使用

​一、下载安装​ 1.打开官网下载 https://www.xshell.com/zh/free-for-home-school/ 2.选择合适的下载路径&#xff0c;点击下载按钮&#xff0c;然后按照提示完成安装。 二、Xshell7的使用&#xff0c;Xhell连接Linux 1.连接之前&#xff0c;确保在Linux中开启SSH。参考&a…

VBA学习(15):工作表加密保护后却把密码忘记了?

今天把过去的一篇推文重新整理一下&#xff0c;提供两种解除工作表加密的方法。 一种是傻瓜模式的VBA&#xff0c;复制运行以下代码&#xff0c;即可抹除当前工作簿所有工作表的保护加密。 Sub UnProtct()MsgBox "破解提示&#xff1a;当要求输入密码时请点击取消&#…

Pnpm:包管理的新星,如何颠覆 Npm 和 Yarn

在探索现代 JavaScript 生态系统时&#xff0c;我们常常会遇到新兴技术的快速迭代和改进。其中&#xff0c;包管理工具的发展尤为重要&#xff0c;因为它们直接影响开发效率和项目性能。最近&#xff0c;pnpm 作为一种新的包管理工具引起了广泛关注。它不仅挑战了传统工具如 np…