为什么mysql删除不了数据库_为什么MySQL不建议delete删除数据
这篇文章我会从InnoDB存储空间分布,delete对性能的影响,以及优化建议方面解释为什么不建议delete删除数据。
InnoDB存储架构
从这张图可以看到,InnoDB存储结构主要包括两部分:逻辑存储结构和物理存储结构。
逻辑上是由表空间tablespace —> 段segment或者inode —> 区Extent ——>数据页Page构成,Innodb逻辑管理单位是segment,空间分配的最小单位是extent,每个segment都会从表空间FREE_PAGE中分配32个page,当这32个page不够用时,会按照以下原则进行扩展:如果当前小于1个extent,则扩展到1个extent;当表空间小于32MB时,每次扩展一个extent;表空间大于32MB,每次扩展4个extent。
物理上主要由系统用户数据文件,日志文件组成,数据文件主要存储MySQL字典数据和用户数据,日志文件记录的是data page的变更记录,用于MySQL Crash时的恢复。
Innodb表空间
InnoDB存储包括三类表空间:系统表空间,用户表空间,Undo表空间。
**系统表空间:**主要存储MySQL内部的数据字典数据,如information_schema下的数据。
**用户表空间:**当开启innodb_file_per_table=1时,数据表从系统表空间独立出来存储在以table_name.ibd命令的数据文件中,结构信息存储在table_name.frm文件中。
**Undo表空间:**存储Undo信息,如快照一致读和flashback都是利用undo信息。
从MySQL 8.0开始允许用户自定义表空间,具体语法如下:
这样的好处是可以做到数据的冷热分离,分别用HDD和SSD来存储,既能实现数据的高效访问,又能节约成本,比如可以添加两块500G硬盘,经过创建卷组vg,划分逻辑卷lv,创建数据目录并mount相应的lv,假设划分的两个目录分别是/hot_data 和 /cold_data。
这样就可以将核心的业务表如用户表,订单表存储在高性能SSD盘上,一些日志,流水表存储在普通的HDD上,主要的操作步骤如下:
Inndob存储分布
创建空表查看空间变化
设置参数innodb_file_per_table=1时,创建表时会自动创建一个segment,同时分配一个extent,包含32个data page的来存储数据,这样创建的空表默认大小就是96KB,extent使用完之后会申请64个连接页,这样对于一些小表,或者undo segment,可以在开始时申请较少的空间,节省磁盘容量的开销。
插入数据后的空间变化
delete数据后的空间变化
MySQL内部不会真正删除空间,而且做标记删除,即将delflag:N修改为delflag:Y,commit之后会会被purge进入删除链表,如果下一次insert更大的记录,delete之后的空间不会被重用,如果插入的记录小于等于delete的记录空会被重用,这块内容可以通过知数堂的innblock工具进行分析。
Innodb中的碎片
碎片的产生
我们知道数据存储在文件系统上的,总是不能100%利用分配给它的物理空间,删除数据会在页面上留下一些”空洞”,或者随机写入(聚集索引非线性增加)会导致页分裂,页分裂导致页面的利用空间少于50%,另外对表进行增删改会引起对应的二级索引值的随机的增删改,也会导致索引结构中的数据页面上留下一些"空洞",虽然这些空洞有可能会被重复利用,但终究会导致部分物理空间未被使用,也就是碎片。
同时,即便是设置了填充因子为100%,Innodb也会主动留下page页面1/16的空间作为预留使用(An innodb_fill_factor setting of 100 leaves 1/16 of the space in clustered index pages free for future index growth)防止update带来的行溢出。
其中data_free是分配了未使用的字节数,并不能说明完全是碎片空间。
碎片的回收
对于InnoDB的表,可以通过以下命令来回收碎片,释放空间,这个是随机读IO操作,会比较耗时,也会阻塞表上正常的DML运行,同时需要占用额外更多的磁盘空间,对于RDS来说,可能会导致磁盘空间瞬间爆满,实例瞬间被锁定,应用无法做DML操作,所以禁止在线上环境去执行。
delete对SQL的影响
未删除前的SQL执行情况
删除后的SQL执行情况
结果统计分析
这也说明对普通的大表,想要通过delete数据来对表进行瘦身是不现实的,所以在任何时候不要用delete去删除数据,应该使用优雅的标记删除。
delete优化建议
控制业务账号权限
对于一个大的系统来说,需要根据业务特点去拆分子系统,每个子系统可以看做是一个service,例如美团APP,上面有很多服务,核心的服务有用户服务user-service,搜索服务search-service,商品product-service,位置服务location-service,价格服务price-service等。每个服务对应一个数据库,为该数据库创建单独账号,同时只授予DML权限且没有delete权限,同时禁止跨库访问。
delete改为标记删除
在MySQL数据库建模规范中有4个公共字段,基本上每个表必须有的,同时在create_time列要创建索引,有两方面的好处:
一些查询业务场景都会有一个默认的时间段,比如7天或者一个月,都是通过create_time去过滤,走索引扫描更快。一些核心的业务表需要以T +1的方式抽取数据仓库中,比如每天晚上00:30抽取前一天的数据,都是通过create_time过滤的。
数据归档方式
通用数据归档方法
优化后的归档方式
这样原表和归档表都是按月的分区表,只需要创建一个中间普通表,在业务低峰期做两次分区交换,既可以删除无效数据,又能回收空,而且没有空间碎片,不会影响表上的索引及SQL的执行计划。
总结
通过从InnoDB存储空间分布,delete对性能的影响可以看到,delete物理删除既不能释放磁盘空间,而且会产生大量的碎片,导致索引频繁分裂,影响SQL执行计划的稳定性;
同时在碎片回收时,会耗用大量的CPU,磁盘空间,影响表上正常的DML操作。
在业务代码层面,应该做逻辑标记删除,避免物理删除;为了实现数据归档需求,可以用采用MySQL分区表特性来实现,都是DDL操作,没有碎片产生。
另外一个比较好的方案采用Clickhouse,对有生命周期的数据表可以使用Clickhouse存储,利用其TTL特性实现无效数据自动清理。
为什么mysql删除不了数据库_为什么MySQL不建议delete删除数据相关推荐
- mysql 将xml插入数据库_从xml文档中读取数据并插入mysql数据库中
// TODO: Add your control notification handler code here CMarkup xml; xml.Load("色谱案例表.xml" ...
- MySQL中创建jxgl数据库_《MySQL数据技术与实验指导》jxgl数据库的创建和插入
简述 之前都是在宿舍的一个台式电脑上写数据库的作业,但是最近需要出去外面比赛,路上可能就需要写作业.所以就打算重新写一遍这个作业.顺便就写一下答案. jxgl这个库之后会需要用到. 环境介绍 wind ...
- mysql主从备份导入数据库_[导入]MySQL数据库的主从及双机备份
花了半天时间研究了下下MYSQL的备份实现,发现其是在MY.CNF(MY.INI)配置文件中作的设置,直接设置服务器唯一性ID号加上其它的附加设 置,则可作为一台MASTER,而在 SLAVE机上,也 ...
- mysql禁止数据被删除_为什么MySQL不建议delete删除数据
我负责的有几个系统随着业务量的增长,存储在MySQL中的数据日益剧增,我当时就想现在的业务方不讲武德,搞偷袭,趁我没反应过来把很多表,很快,很快啊都打到了亿级别,我大意了,没有闪,这就导致跟其Join ...
- delete index mysql_为什么MySQL不建议delete删除数据「心得分享」
前言 我负责的有几个系统随着业务量的增长,存储在MySQL中的数据日益剧增,我当时就想现在的业务方不讲武德,搞偷袭,趁我没反应过来把很多表,很快,很快啊都打到了亿级别,我大意了,没有闪,这就导致跟其J ...
- MySQL 的几种碎片整理方案总结(解决delete大量数据后空间不释放的问题)
MySQL 的几种碎片整理方案总结(解决delete大量数据后空间不释放的问题) 1.背景知识 1.1 为什么会有碎片 MySQL 中 insert 与 update 都可能导致页分裂,这样就存在碎片 ...
- mysql语句删除excel文件夹_使用Excel怎么生成批量删除、新增数据库语句
1.打开Excel,新建一个空白的页签,在A1输入写好的数据库删除语句,DROP DATABASE `db_game_1`; . 2.在A2输入如下公式:="DROP DATABASE `d ...
- mysql核心数据库_从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程...
从MySQL基础进军MySQL核心架构 178集MySQL数据库核心基础视频教程 MySQL基础案例教程 课程目录 (1) 01MySQL基础_课程引入.avi (2) 02MySQL基础_为什么学习 ...
- mysql使用已有的数据库_使用SQL操作MySQL数据库
用SHOW显示已有的数据库 句法:SHOW DATABASES [LIKE wild] 如果使用LIKE wild部分,wild字符串可以是一个使用SQL的"%"和"_& ...
最新文章
- 几款自用的IDEA高效插件
- 【转】G40-70、G50-70联想小新笔记本SR1000随机Linux改Windows 7系统操作指导
- 测试之美---测试员的心思你不懂
- 使用 Boost.Lambda 库创建并存储在 Boost.Function 对象中的函子中使用 Boost.Units 的数量、单位和绝对类型
- Retrofit+RxJava联网工具类
- git pull 覆盖本地_SVN与Git比较的优缺点差异
- android id 重名_android - 解决“应用自定义权限重名”
- 在Java 中 使用 AWS SNS 来发送短信的例子
- Linux命令行配置网络(有线网络,无线网络)// Debian
- qq互联--qq登录例子 java版 源码_PHP版QQ互联OAuth示例代码分享
- 微信企业付款转账到微信
- 【地图可视化】Echarts地图上展示3D柱体
- 广告主选择在今日头条推广的优势有哪些?头条搜索广告怎么做?
- el-date-picker修改为周类型日期插件时间格式是开始时间字段级和结束时间字段两个传参给后台
- android softkeyboard,如何以编程方式关闭Android Soft KeyBoard?
- win10计算机自带的游戏怎么打开方式,win10自带游戏及应用打不开,应用商店闪退无法使用...
- 解决windows11屏幕亮度忽明忽暗的问题
- 生成13位条形码 Ean-13码规则: 第十三位数字是前十二位数字经过计算得到的校验码。
- 人工智能及其在电力系统中的应用专业就业
- 壁纸小程序源码,支持图片搜索,下载,分享,可对接流量主