讲讲MySQL的删除

MySQL的delete操作并不真正删除数据,而是设置删除标识。purge线程负责回收可复用空间,但未被利用可能导致空间浪费。B+树索引允许高效检索,分表决定不应仅基于数据行数。页合并与分裂影响空间利用率,重建表可能因预留空间导致空间变化。手动重建表可能因预留1/16空间使表变大。
摘要由CSDN通过智能技术生成

eaeae735766d6152bb3c5d45a00283c7.png

若有收获,请记得分享和转发哦

20d124113542f259f365f15851ef0dfb.png

删除并不是真正的删除

熟悉mysql的同学都应该知道,当我们执行delete的时候,数据并没有被真正的删除,只是对应数据的删除标识deleteMark被打开了,这样每次执行查询的时候,如果发现数据存在但是deleteMark是开启的话,那么依然返回空,因为这个细节,所以经常会出现“我明明删除了数据,为什么空间没释放”的现象。

15M  7  6 18:46 user_info.ibd #删除前
15M 10  4 16:47 user_info.ibd #删除后
为什么不直接删除,而是打个标记

1a188e2ca3c2a2397393ab8c1570ca9d.png

只是打个标记的话,岂不是很浪费空间

mysql里面有个purge线程,它的工作中有一项任务就是专门检查这些有deleteMark的数据,当有deleteMark的数据如果没有被其他事务引用时,那么会被标记成可复用,因为叶子节点数据是有序的原因,这样当下次有同样位置的数据插入时,可以直接复用这块磁盘空间。当整个页都可以复用的时候,也不会把它还回去,会把可复用的页留下来,当下次需要新页时可以直接使用,从而减少频繁的页申请。

450875c317c7d1c00b1264bbeb16024c.png

754b966492d8a8bb18ffc0f50754f0ca.png

3274e229dda47db7897aba7069412ccb.png

通过上面我们知道检索一条数据的快慢,主要受树的高度影响的,这和你的数据表的大小并没有太大的关系,现实中有人可能在数据表达到百万级别的时就考虑分表,个人认为这有点低估B+树的能力了。还是以bigint类型的主键索引为例,假设一行数据占用1K(理论上已经足够大了),那么一页可以存下 16K/1K=16 条数据,对于一颗高度为3的B+树来说,它可以存下 1170*1170*16=21902400 的数据,将近2千万,如果你的数据行占用的空间更小,就可以存下更多的数据,所以只是简单的根据数据行数来判断是否需要分表不是那么的合理。

可复用的空间一直没有被利用咋办

63f74cc37af2439c98101c51c56c2cce.png

857839fb2a6983b5fdd6862b73061b31.png

825000828c80797b9d13a1838da631c7.png

有合并也有分裂

合并页是提升页的利用率的方式,但是有时候我们又不得不分裂页,我们知道叶子节点的页之间是用双向链表串接起来的,并且页与页之间的数据是有序的。

06b6044f2310c7d8ca19c6c928e7468f.png

以上图为例,当我们要插入5这条数据,按道理应该尝试放在pageA里面,但是pageA目前没有足够的空间来存放一条数据,于是尝试找到pageA的相邻页pageB,但是此时很不幸的是pageB也没有足够的空间来存放一条数据,由于要求数据的连续性,数据5必须在数据4和数据6之间,那么只能新建一个页,新建一个页后,会尝试从pageA中移动一部分数据到新的页上,并且会重新组织页与页之间的关系,即在pageA和pageB之间会隔一道新页pageC。

e547e84a316c2f74968613b361619fdf.png

页分裂会造成页的利用率降低,造成页分裂的原因有很多,比如:

  1. 比如离散的插入,导致数据不连续。

  2. 把记录更新成一个更大记录,导致空间不够用

还有一点需要知道的是:不管是页的合并还是页的分裂,都是相对耗时的操作,除了移动数据的开销外,InnoDB也会在索引树上加锁。

手动重建表

6798a79fe791211c8193488b51267059.png

a4302c1b07a51a2265b0ed07c59aecd1.png

重建表不一定会收缩空间

在重建表的过程中,有一点需要知道:InnoDB不会让重建后的页充满数据,会预留个「1/16」的空间,这个意图很明显,如果不预留,选择占满整个页,这时候去更新一条需要更大空间的老数据,就会需要新的页,写入新的页后,往往又会造成碎片,所以提前预留一点空间是有用的。

但是因为这个预留操作,某些情况下会导致重建后的表空间反而会变大。

  1. 如果你的表本身就很紧凑,因为预留1/16会变大。

  2. 在第一次重建表后,因为新的插入导致用掉了预留空间的一部分(这里需要注意的是预留空间没用完,还剩一部分),但是没有用到新的页,所以整体的空间没有变化,这时候如果再次重建表,就会因为要预留1/16,导致申请的新的页,那么空间就会变大。

如果您希望将MySQL安装到指定位置,可以使用以下步骤进行安装: 1. 下载MySQL的RPM安装包,并解压缩到指定目录。例如: ``` wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm rpm2cpio mysql80-community-release-el7-3.noarch.rpm | cpio -idmv mv ./etc/yum.repos.d/mysql-community.repo /etc/yum.repos.d/ mkdir -p /opt/mysql cd /opt/mysql yumdownloader --destdir . mysql-community-server rpm2cpio mysql-community-server-8.0.25-1.el8.x86_64.rpm | cpio -idmv ``` 上述命令将下载MySQL的RPM包,并解压缩到/opt/mysql目录中。 2. 安装MySQL服务器和客户端。可以使用以下命令进行安装: ``` sudo yum --installroot=/opt/mysql -y install mysql-community-server mysql-community-client ``` 该命令将在/opt/mysql目录下安装MySQL服务器和客户端。 3. 启动MySQL服务并设置开机自启动。可以使用以下命令启动MySQL服务: ``` sudo systemctl --root=/opt/mysql start mysqld ``` 然后使用以下命令设置MySQL服务开机自启动: ``` sudo systemctl --root=/opt/mysql enable mysqld ``` 4. 安全设置MySQL。可以使用以下命令进行MySQL安全设置: ``` sudo /opt/mysql/usr/bin/mysql_secure_installation ``` 该命令将引导您设置MySQL的root用户密码、删除匿名用户、禁止root用户远程登录等安全设置。 安装完成后,您可以使用以下命令检查MySQL服务是否正常运行: ``` sudo systemctl --root=/opt/mysql status mysqld ``` 如果MySQL服务正常运行,您应该可以看到类似以下的输出: ``` ● mysqld.service - MySQL Server Loaded: loaded (/opt/mysql/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: active (running) since Mon 2021-06-21 16:49:37 CST; 3h 13min ago ``` 这表示MySQL服务器已经成功安装并运行在指定位置/opt/mysql中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值