暂无图片
暂无图片
11
暂无图片
暂无图片
1
暂无图片

Mysql空间清理

原创 黄超 2020-08-31
6169

在Mysql环境下,常常由于数据磁盘满而导致Mysql故障。下面整理了如何在Mysql(5.7)环境下做好Mysql的空间清理。

一、日志文件清理

Mysql的日志日积月累,占用的磁盘空间越来越大,磁盘可用空间越来越少,需要自动清理或者手动清理

  • 1.查看文件磁盘占用
    1.1 查看磁盘空间占用
# df -lh
Filesystem             Size  Used Avail Use% Mounted on
devtmpfs               1.9G     0  1.9G   0% /dev
tmpfs                  1.9G   17M  1.9G   1% /dev/shm
tmpfs                  1.9G  177M  1.7G  10% /run
tmpfs                  1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/vda1              4.8G  3.8G  833M  83% /
/dev/mapper/sys-lv--2  5.8G  3.0G  2.6G  54% /usr
/dev/vda2              980M   93M  820M  11% /boot
/dev/vdb                99G   41G   53G  44% /opt
/dev/mapper/sys-lv--3  4.8G  2.6G  2.0G  57% /var
/dev/mapper/sys-lv--4  976M  2.0M  907M   1% /root
/dev/mapper/sys-lv--5  7.8G  1.3G  6.1G  18% /tmp
tmpfs                  383M     0  383M   0% /run/user/6351
tmpfs                  383M     0  383M   0% /run/user/7831
tmpfs                  383M     0  383M   0% /run/user/0
复制

1.2 查看目录空间占用

# du -sh /opt
41G     /opt
复制

1.3 查看文件空间占用

# ll -h /mysql/data/binlog/binlog/mysql-bin.000175
-rw------- 1 mysql oinstall 110M Nov  8 09:15 /mysql/data/binlog/binlog/mysql-bin.000175
复制
  • 2.Binlog日志清理
    2.1定时自动清理Binlog日志

    查看当前日志保存天数:

mysql>show variables like '%expire_logs_days%';
复制

这个默认是0,也就是logs不过期,可通过设置全局的参数,使他临时生效:
 
 mysql>set global expire_logs_days=10;

设置了只保留10天BINLOG, 下次重启mysql这个参数默认会失败,所以需在my.cnf中设置
expire_logs_days = 10
这样在下次重启mysql的时候,expire_logs_days也一样是10;

2.2 手动删除Binlog日志
第一步:登陆进入mysql,并使用 show binary logs; 查看日志文件。
mysql>show binary logs;
±-----------------±----------+
| Log_name | File_size |
±-----------------±----------+
| mysql-bin.000001 | 234592362 |
| mysql-bin.000002 | 425234342 |
| mysql-bin.000003 | 425345345 |
| mysql-bin.000004 | 234234222 |
| mysql-bin.000005 | 425994852 |
±-----------------±----------+
1 row in set (0.00 sec)
第二步:查看正在使用的日志文件:show master status;
mysql>show master status;
±-----------------±----------±-------------±-----------------±------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
±-----------------±----------±-------------±-----------------±------------------+
| mysql-bin.000005 | 425994852 | | | |
±-----------------±----------±-------------±-----------------±------------------+
1 row in set (0.00 sec)
当前正在使用的日志文件是mysql-bin.000005,那么删除日志文件的时候应该排除掉该文件。
删除日志文件的命令:purge binary logs to ‘mysql-bin.000005’;
mysql>purge binary logs to ‘mysql-bin.000005’;
删除除mysql-bin.000005以外的日志文件,也可以指定其他文件名,例如mysql-bin.000003。
删除后就能释放大部分空间。

  • 3.Slow日志清理
    3.1Slow日志为TABLE模式
    步骤一 查看Slow日志模式为TABLE
    mysql>show variables like ‘log_output%’;

±--------------±------+
| Variable_name | Value |
±--------------±------+
| log_output | TABLE |
±--------------±------+
1 row in set (0.00 sec)

步骤二 Slow表改名,生成同样表结构的新Slow表,删除原Slow表

mysql>use mysql;
mysql>SET GLOBAL slow_query_log = ‘OFF’;
mysql>ALTER TABLE slow_log RENAME slow_log_drop;
mysql>CREATE TABLE slow_log LIKE slow_log_drop;
mysql>SET GLOBAL slow_query_log = ‘ON’;
mysql>DROP TABLE slow_log_drop;

3.2Slow日志为FILE模式
步骤一 查看slow日志模式为FILE
mysql>show variables like ‘log_output%’;
±--------------------±--------+
| Variable_name | Value |
±--------------------±--------+
| log_output | FILE |
±--------------------±--------+
1 row in set (0.08 sec)

步骤二 查看Slow日志文件位置

mysql>show variables like ‘%slow%’;
±--------------------------±----------------------------------------+
| Variable_name | Value |
±--------------------------±----------------------------------------+
| log_slow_admin_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 5 |
| slow_query_log | ON |
| slow_query_log_file | /mysql/data/log/slow/mysql-slow.log |
±--------------------------±----------------------------------------+
5 rows in set (0.00 sec)

步骤三 清空Slow日志

# cd /mysql/data/log/slow/
# echo “”>mysql-slow.log
复制

4.Error日志清理
步骤一 查看error日志位置

mysql>show variables like ‘log_error’;
±--------------±-------------------------------------+
| Variable_name | Value |
±--------------±-------------------------------------+
| log_error | /mysql/data/log/error/mysqld.log |
±--------------±-------------------------------------+
1 row in set (0.01 sec)

步骤二 查看error日志大小

# ll -h /mysql/data/log/error/mysqld.log
-rw------- 1 mysql oinstall 252K Nov 28 09:24 /mysql/data/log/error/mysqld.log
复制

步骤三 清空error日志

# echo “”>/mysql/data/log/error/mysqld.log
复制

二、表清理

大表,指单个数据文件磁盘占用大于100G,或者单个表数据记录量大于1亿。可以根据自己具体环境确定。

  • 1.查看表占空间和记录数

mysql>select table_schema,table_name, concat(round((data_length+index_length)/1024/1024/1024,2),‘G’) as tablesize_gb, table_rows from information_schema.tables where table_schema=‘admin’ order by tablesize_gb desc limit 5;
±-------------±----------------------±-------------±-----------+
| table_schema | table_name | tablesize_gb | table_rows |
±-------------±----------------------±-------------±-----------+
| admin | ef_cdr_format_def | 0.15G | 5139 |
| admin | t_bme_taskrunresult | 0.12G | 762584 |
| admin | ef_cdr_field_ext_rule | 0.08G | 1585 |
| admin | t_bme_operationlog | 0.07G | 206496 |
| admin | ef_factor_analysis | 0.06G | 148 |
±-------------±----------------------±-------------±-----------+
5 rows in set (0.90 sec)

table_schema:库名
table_name :表名
tablesize_gb:表占空间大小,以G为单位
table_rows:行数

  • 2.常规表数据清理
    常规表指没达到大表标准的。

Delete
语法:Delete from table_name [ where condition]
Delete 只删除符合条件的数据,不会减少表所占空间。
Delete大量数据后,会存在碎片,需要整理回收碎片空间
optimize table table.name 或者 alter table table.name engine=‘innodb’ (会锁表,注意在业务低谷期执行)

Truncate
语法:Truncate table table_name
Truncate 删除全表数据,回收所占表空间。

Drop
语法:Drop table table_name
Drop 删除全表数据和表结构,回收所占表空间。

  • 3.大表删除
    大表 Drop 表的时候,所有Mysql的相关进程都会停止,直到Drop结束,耗时时间很长,若是生产环境,会阻塞业务访问。出现这情况是因为,在drop table的时候,innodb维护了一个全局锁,drop完毕锁才释放。

3.1表改名
new_t_test克隆原t_test的表结构
mysql>create table new_t_test like t_test;
原t_ test改名old_t_ test,新表new_t_ test改名t_ test;
mysql>rename table t_ test to old_t_ test,new_t_ test to t_ test;

3.2建立硬链接
命令:ln 源文件 硬链接文件
mysql>system ln /mysql/data/workdbs/admin/t_test.ibd /mysql/data/workdbs/admin/t_test.ibd.hdlk
此时,文件目录如下所示

-rw-r----- 1 mysql oinstall 9023 8 18 05:21 t_test.frm
-rw-r----- 2 mysql oinstall 2356792000512 8 18 05:21 t_test.ibd
-rw-r----- 2 mysql oinstall 2356792000512 8 18 05:21 t_test.ibd.hdlk
你会发现,多了一个t_test.ibd.hdlk文件,且t_test.ibd和t_test.ibd.hdlk的inode均为2。也即当有多个文件名(如硬链接)指向同一innode时,这个innode的引用数大于1,此时,删除其中任何一个文件名都只会删除指向innode的指针而并不会直接删除物理文件块,因此会非常快,直至innode的引用计数等于1时才会真正删除对应的物理文件块,真正删除物理文件块时才会比较耗时。

3.3Drop大表
执行Drop table操作
mysql>drop table t_test;
Query OK, 0 rows affected (0.99 sec)
t_test表已从数据库中删除,但是磁盘空间还没释放,还剩一个文件t_test.ibd.hdlk,且innode的引用计数变为了1。也即刚才的DROP TABLE操作实施删除了物理文件的一个指针t_test.ibd ,因而非常快。

3.4删除物理文件
物理文件较大,删除大文件仍会引起较高的磁盘IO开销。因此可以使用少量逐次删除的方式来删除大的数据文件。truncate工具可以用于增加或缩减指定文件的尺寸,删除脚本如下:
for i in seq 100 -1 1 ;do sleep 2;sudo truncate -s ${i}G /mysql/data/workdbs/admin/t_test.ibd.hdlk;done
rm -rf /mysql/data/workdbs/admin/t_test.ibd.hdlk;
从100G开始,每次缩减1G,停2秒,继续,直到文件只剩1G,最后使用rm命令删除剩余的部分。

对于整个数据库的删除可以先删除其中较大的表,最后再执行DROP DATABASE删除整个库,对大表的删除可参见上面的方法。

注:在生产环境下,注意做好Mysql存储数据的磁盘使用率的监控和报警。

最后修改时间:2020-09-03 10:00:20
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
1人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论

筱悦星辰
暂无图片
1年前
评论
暂无图片 0
生活从来没有捷径,当你知道自己想要的是什么时,制定计划、勇敢出发,让梦想照进现实。只要你勇敢前行,生活早晚会给你意想不到的惊喜。
1年前
暂无图片 点赞
评论