MySQL超大表删除数据过程
背景
笔者在公司负责公司的OpenAPI应用,估产生了调用审计的需求。对于存储这些AccessLog,虽然业界有很合适的架构和理论,奈何我司已成本优先,且作为toB的项目,调用量并不算特别大,每天也就2G左右的AccessLog产生。业务特征又导致整个订单的周期非常长,最少要保存1年以上的记录,以备排查问题所用(扯皮甩锅)。所以使用了大磁盘的MySQL直接存储。其表结构如下:
CREATE TABLE `access_log` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`trace_id` varchar(50) DEFAULT NULL COMMENT 'traceId',
`api_name` varchar(50) DEFAULT NULL COMMENT 'api名称',
`api_context` longtext COMMENT '调用正文',
`api_result` longtext COMMENT '返回正文',
`is_success` tinyint(4) DEFAULT NULL COMMENT '是否成功',
`time_consuming` bigint(20) DEFAULT NULL COMMENT '消耗时间(毫秒)',
PRIMARY KEY (`id`),
KEY `idx_trace_id` (`trace_id`),
KEY `idx_gmt_create` (`gmt_create`,`api_name`),
KEY `idx_api_name` (`api_name`,`gmt_create`,`is_success`)
) ENGINE=InnoDB COMMENT='流量入口-api记录'
而随着业务发展,需要接入的系统也越来越多,甚至有定时任务需要轮询接口,导致日志量暴增。达到了日均40G的地步。单表最大数据量在600G
在此期间,使用了各种手段优化写入量。忽略某些超高频又不影响业务的API。只记录某些接口错误调用的日志等等。
至于为什么不采用以月为后缀的动态表,涉及到我司DB管控问题。该方案一直无法通过。
问题拖到现在,涉及两张表:accessLog 600G, errorLog 200G。存储已经达到了物理机的上限,扩容就需要进行数据库迁移,最少需要一周时间提前做数据迁移。
要求
现状:
- 两张超大表:accessLog 600G, errorLog 200G。
- 近两周暴增了400G的占用
- 整个机器的存储空间已经达到91%。剩余90G左右空间。
要求:
- 线上做到写入无影响。
- 数据库不能因此宕机。
技术方案
因为涉及的表过大,操作必须谨慎,不能产生临时表,表重建等隐形操作。
流程如下:
- 清理errorLog表,只留存3天数据
- 检查实际空间占用,确定重建表的空间安全
- 重建该表,将可用空间提升到200G左右
- 归档accessLog表
- 清理其超高频的API日志
- 按照日期保留3个月的日志
- 检查实际空间占用,确定重建时空间安全。
- 说服DBA,同意基于日期的动态表方案。
清理数据
清理数据相对简单,只需要加上主键排序+limit即可
delete from table_name where *** order by id limit 10000;
但是在清理过程中需要注意binlog文件大小,因为binlog一般配置了按天保存文件,可能导致binlog打满磁盘的情况。
查看binlog文件大小
show binary logs;
| Log_name | File_size|
| mysql-bin.003312 | 15178497 |
| mysql-bin.003313 | 3841846 |
| mysql-bin.003314 | 12789083 |
| mysql-bin.003315 | 9800029 |
查看正在写入的Binlog文件
show master status;
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
| mysql-bin.003315 | 10479164 | | | **** |
执行过程中,需要暂停一段时间执行,方便binlog切换等操作,否则可能导致实例一直繁忙状态无法生成新的binlog文件
清理历史binlog文件
PURGE MASTER LOGS TO 'mysql-bin.003315';
--- 清理 mysql-bin.003315 之前的文件,并不会清理当前文件。
清理完成后可以再次查看binlog文件
检查实际空间大小
因为MySQL的物理删除本质上也是逻辑删除,所以空间并不会被释放,需要检查实际的空间占用,保证重建表时,空间在安全范围内。
SELECT CONCAT(table_schema, '.', table_name) AS 'Table Name',
CONCAT(ROUND(table_rows / 1000000, 4), 'M') AS 'Number of Rows',
CONCAT(ROUND(data_length / (1024 * 1024 * 1024), 4), 'G') AS 'Data Size',
CONCAT(ROUND(index_length / (1024 * 1024 * 1024), 4), 'G') AS 'Index Size',
CONCAT(ROUND((data_length + index_length) / (1024 * 1024 * 1024), 4), 'G')
AS 'Total',
CONCAT(ROUND((data_free) / (1024 * 1024 * 1024), 4), 'G')
AS 'Free Size'
FROM information_schema.TABLES
WHERE table_schema LIKE 'database_name';
替换掉database_name为数据库名称,则可以看到表有效数据的占用大小,可释放空间大小等等。
如Total>数据库剩余空间,则重建就是安全的。
重建表
重建表使用一下语句:
OPTIMIZE TABLE `table_name`;
该命令会重建表
结果
清理数据过程中
- 180 IOPS左右浮动
- CPU在20%左右
- 磁盘空间无明显增长
重建过程中
- 6000左右的 IOPS,完全吃满了磁盘性能
- CPU 40%左右浮动
- 磁盘初始新增20GB,后续断崖式下降
原文:https://blog.lianglianglee.com/2023/09/12/mysql-big-table-clean-data/
MySQL超大表删除数据过程的更多相关文章
- python + mysql 实现表删除数据
实例如下: import pymysqldef Delete_From(): #打开数据库链接 db = pymysql.connect("localhost","roo ...
- MySQL数据库表的数据插入、修改、删除、查询操作及实例应用
一.MySQL数据库表的数据插入.修改.删除和查询 CREATE DATABASE db0504; USE db0504; CREATE TABLE student ( sno ) NOT NULL ...
- Mysql添加更新删除数据-表
例如 此处拥有一个表名为 uuser 为表添加新数据 ,'); ,'); ,'); 假如只想添加uid和uname ,'小张'); 那么pas自动填充为NULL. 为表更新数据 这里把小王的pas改成 ...
- MySQL 创建和删除数据表
创建MySQL数据表需要以下信息: 表名 表字段名 定义每个表字段 语法 以下为创建MySQL数据表的SQL通用语法: CREATE TABLE table_name (column_name col ...
- MySQL多表关联数据同时删除
MySQL多表关联时的多表删除: DELETE t1, t2FROM t1LEFT JOIN t2 ON t1.id = t2.idWHERE t1.id = 25
- mysql跨表删除多条记录
Mysql可以在一个sql语句中同时删除多表记录,也可以根据多个表之间的关系来删除某一个表中的记录. 假定我们有两张表:Product表和ProductPrice表.前者存在Product的基本信息, ...
- MySQL单表百万数据记录分页性能优化
背景: 自己的一个网站,由于单表的数据记录高达了一百万条,造成数据访问很慢,Google分析的后台经常报告超时,尤其是页码大的页面更是慢的不行. 测试环境: 先让我们熟悉下基本的sql语句,来查看下我 ...
- MySQL 单表百万数据记录分页性能优化
文章转载自:http://www.cnblogs.com/lyroge/p/3837886.html 背景: 自己的一个网站,由于单表的数据记录高达了一百万条,造成数据访问很慢,Google分析的后台 ...
- oracle 大表删除数据后,回收空间的问题。
在oracle中由于表结构设计不合理或者需要清楚老数据的时候,经常需要对大表数据进行清理. 一般有一下几种方法: 1. 删除大部分数据,留下小部分数据.我们可以把需要保留的数据转移到别的表,然后再把大 ...
- MySQL单表百万数据记录分页性能优化,转载
背景: 自己的一个网站,由于单表的数据记录高达了一百万条,造成数据访问很慢,Google分析的后台经常报告超时,尤其是页码大的页面更是慢的不行. 测试环境: 先让我们熟悉下基本的sql语句,来查看下我 ...
随机推荐
- SQL语句报com.alibaba.druid.sql.parser.ParserException: TODO IDENTIFIER cross
这个错误根据网络上人员说是解析出错!虽然报错但不影响结果!但是报错了就是看的不爽!把druid包换成druid-1.0.9.jar就解决这个问题了!至于性能暂时还没测试到
- Qt/C++音视频开发50-不同ffmpeg版本之间的差异处理
一.前言 ffmpeg的版本众多,从2010年开始计算的项目的话,基本上还在使用的有ffmpeg2/3/4/5/6,最近几年版本彪的比较厉害,直接4/5/6,大版本之间接口有一些变化,特别是一些废弃接 ...
- springboot的Web项目编译运行时提示错误:Field userService in com.cetc.UserManger.controller.UserController required a bean of type 'com.cetc.UserManger.service.UserService' that could not be found.
错误描述: springboot的Web项目编译运行时提示错误:Field userService in com.cetc.UserManger.controller.UserController r ...
- C#操作MySQL数据库——思路简单清晰
1.下载mysql.Data.dll,在解决方案->引用中引入,并在文件头部引入 using MySql.Data.MySqlClient; 2.创建MySqlConnection对象(链接库) ...
- ImageSharp:高性能跨平台.NET开源图形库
在.Net中,System.Drawing有平台限制的问题,如果需要跨平台就需要使用第三方库. 今天推荐一个.NET开源图形库,不依赖任何库,支持跨平台的图形库. 01 项目简介 ImageSharp ...
- 使用GPIO判断网线拔插
USB网卡和以太网交换机"常连"后,增加交换机插拔网线判断机制 这个项目已经做了小半年了,客户是一个做智能电话机的.所谓的智能电话就是一台可以插网线.电话线,外观却是座机的手机. ...
- 前端学习openLayers配合vue3(获取矢量图的个数,省份的个数)
矢量图层绘制了一个中国地图,我们获取一下矢量图层的个数 关键代码 map .getLayers()//获取所有图层 .item(1)//获取矢量图层 .getSource() .on("ch ...
- Java虚拟机调优-基本垃圾回收算法
背景: 可以从不同的的角度去划分垃圾回收算法: 按照基本回收策略分 引用计数(Reference Counting): 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一 ...
- 金山毒霸提示这是高危入侵行为taskeng.exe
如果安装了金山毒霸之后经常会弹窗提示:这是高位入侵行为.行为发起taskeng.exe.可疑进程regsvr32.EXE,可疑路径antivirus.php,如下入所示: 可以直接点击"阻止 ...
- C#客户端Json转DataTable
本文转自 https://blog.csdn.net/pinebud55/article/details/52240287 感谢pinebud55分享 之前我们有讨论过c#是如何处理json的,在我的 ...