先说结论后看具体场景
rm 删除文件后,如果文件正被进程使用,是不会被真实删除的。虽然执行了rm命令但其仍然存在于磁盘中且被进程引用。
重启进程服务后会被真正删除
MySQL单表太大,但表数据又没什么用的时候,可以通过truncate table来实现。
如果你心存疑问,为什么不使用delete from table where
来定时删除呢?
因为在删除sql语句中,写法如下:DELETE FROM ueb_logistics_rule_logs WHERE type=0 LIMIT 100;
凡是这样,delete带有where条件的,都不是真删除,只是MySQL给记录加了个删除标识,自然这样操作后表数据占有空间也不会变小了。
具体可以复习一下 mysql 的 mvcc 多版本并发控制。
MVCC 机制的实现就是通过 read-view 机制与 undo 版本链比对机制,使得不同的事务会根据数据版本链对比规则读取 同一条数据在版本链上的不同版本数据。
delete 对于删除情况可以认为是 update 的特殊情况,会将版本链上最新的数据复制一份,然后将 trx_id 修改成删除操作的 trx_id,同时在该条记录的头信息(record header)里的标记位(delete flag)写上 true,表示当前记录已经被删除,在查询时按照上面的规则查询对应的记录,如果删除标记位为 true,意味着记录已经被删除,则不返回数据。
解决办法:
OPTIMIZE TABLE 来回收未使用的空间,并整理数据文件的碎片。
但是 OPTIMIZE TABLE只对MyISAM, BDB表起作用,。
innodb的数据库不支持optimize,可以用 ALTER TABLE tableName ENGINE='InnoDB'
(前提是innodb_file_per_table = ON)
该方法会对旧表以复制的方式新建一个新表,然后删除旧表。虽然这个过程是安全的,但是在进行操作时还是先进行备份为好。
然后对表的索引信息做重新统计。尤其是当表数据量级比较大的时候,还是谨慎使用。
analyze table tableName
truncate方法和delete form where 方法都有人使用过了,当然这也是本能想到的方法。但我偏要剑走偏锋,于是我选择了另外一个有坑的不太好的方法,虽然如此,但因为是开发环境无所顾忌,且还学习到了东西。very good。
直接删除ibd文件,以为这样可以立即释放空间,但事与愿违,空间没有一丝一毫的释放。那么空间去哪里了呢,找了垃圾回收站,里边没有。于是开始挨个目录运行du -h --max-depth=1|sort -r -h
,也没有定位到,奇怪了。
然后,徐东成告诉我用lsof
命令试试。
[root@test mnt]# lsof | grep delete
beam.smp 541 601 polkitd 67w REG 0,40 1292 45630035 /var/log/rabbitmq/log/crash.log.3 (deleted)
sys\_sig\_d 541 600 polkitd 67w REG 0,40 1292 45630035 /var/log/rabbitmq/log/crash.log.3 (deleted)
sys\_msg\_d 541 601 polkitd 67w REG 0,40 1292 45630035 /var/log/rabbitmq/log/crash.log.3 (deleted)
async\_1 541 602 polkitd 67w REG 0,40 1292 45630035 /var/log/rabbitmq/log/crash.log.3 (deleted)
async\_2 541 603 polkitd 67w REG 0,40 1292 45630035 /var/log/rabbitmq/log/crash.log.3 (deleted)
[root@test mnt]# lsof | grep delete|grep sy_job_log
mysqld 884 mysql 64uW REG 253,0 49782194176 17871262 /data/mysql_data/hap_job_yl/sy_job_log.ibd (deleted)
mysqld 884 885 mysql 64uW REG 253,0 49782194176 17871262 /data/mysql_data/hap_job_yl/sy_job_log.ibd (deleted)
mysqld 884 886 mysql 64uW REG 253,0 49782194176 17871262 /data/mysql_data/hap_job_yl/sy_job_log.ibd (deleted)
mysqld 884 887 mysql 64uW REG 253,0 49782194176 17871262 /data/mysql_data/hap_job_yl/sy_job_log.ibd (deleted)
mysqld 884 888 mysql 64uW REG 253,0 49782194176 17871262 /data/mysql_data/hap_job_yl/sy_job_log.ibd (deleted)
mysqld 884 889 mysql 64uW REG 253,0 49782194176 17871262 /data/mysql_data/hap
这里的命令lsof | grep delete|grep sy_job_log
用于查找正在使用或引用已删除文件的进程。在你提供的输出中,你正在查找与sy_job_log
相关的删除的文件。
根据输出,可以看到mysqld
进程(MySQL数据库服务器)正在使用名为sy_job_log.ibd
的已删除文件。这通常发生在文件被删除或移动后,但仍然被某个进程打开的情况下。当文件被删除时,文件系统会将其标记为“已删除”,但如果仍然有进程在使用该文件,文件系统不会真正释放磁盘空间。
在这种情况下,你可能需要终止或重新启动相关的mysqld
进程来释放对该文件的引用。你可以尝试以下步骤:
mysqld
进程。mysqld
进程,例如sudo service mysql stop
或sudo systemctl stop mysql
(具体命令取决于你的操作系统和MySQL的安装方式)。mysqld
进程完全停止。mysqld
进程,使用适当的命令,例如sudo service mysql start
或sudo systemctl start mysql
。lsof | grep delete|grep sy_job_log
命令,确认已删除文件是否不再显示在结果中。这样做应该可以解决文件被删除但仍被进程使用的问题。请注意,在执行上述步骤之前,请务必备份重要的数据库文件以防万一。
搞完之后,重启mysql发现重启失败
[root@test hap_job_yl]# sudo service mysql restart
Redirecting to /bin/systemctl restart mysql.service
Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.
[root@test hap_job_yl]# systemctl status mysqld.service
● mysqld.service - LSB: start and stop MySQL
Loaded: loaded (/etc/rc.d/init.d/mysqld; bad; vendor preset: disabled)
Active: failed (Result: exit-code) since 二 2023-08-15 19:06:42 CST; 14s ago
Docs: man:systemd-sysv-generator(8)
Process: 28243 ExecStop=/etc/rc.d/init.d/mysqld stop (code=exited, status=0/SUCCESS)
Process: 29488 ExecStart=/etc/rc.d/init.d/mysqld start (code=exited, status=1/FAILURE)
8月 15 19:06:40 test systemd[1]: Starting LSB: start and stop MySQL...
8月 15 19:06:42 test mysqld[29488]: Starting MySQL.. ERROR! The server quit without updating PID fi...id).
8月 15 19:06:42 test systemd[1]: mysqld.service: control process exited, code=exited status=1
8月 15 19:06:42 test systemd[1]: Failed to start LSB: start and stop MySQL.
8月 15 19:06:42 test systemd[1]: Unit mysqld.service entered failed state.
8月 15 19:06:42 test systemd[1]: mysqld.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
原因是缺少ibd文件,从别的环境搞一个过来
scp sy_job_log.ibd [email protected]:/data/mysql_data/hap_job_yl/
重启还是失败,定位一下原来是复制过来的文件,mysql用户没有权限访问
赋权一下
[root@test hap_job_yl]# chown -R mysql:mysql sy_job_log.ibd
重启okey了。
[root@test hap_job_yl]# sudo service mysql restart