如何高效删除 MySQL 日志表中的历史数据?实战指南
在处理高并发的物联网平台或者其他日志密集型应用时,数据库中的日志表往往会迅速增长,数据量庞大到数百GB甚至更高,严重影响数据库性能。如何有效管理这些庞大的日志数据,特别是在不影响在线业务的情况下,成为了一项技术难题。本文将分享如何高效删除MySQL日志表中的历史数据,并且按月分区管理日志,以提升数据库的读写性能。
一 问题背景:300GB 日志表如何清理?
国庆假期节前检查数据库,发现正在维护一张名为 ali_iot_log
的设备日志表,数据量已经膨胀到380GB,表中的历史数据占据了大量存储,并且严重拖慢了查询和插入的速度。为了优化性能,目标是删除只保留最近3个月的数据。
设备日记表占用385G,如下图:
在MySQL 5.7中,如果这张表没有分区,直接使用delete条件删除历史数据会耗时很较长,并且可能会锁表,影响在线系统的使用。也不能直接清空表,业务系统要求保留最近几个月的数据。那么,如何快速高效地清理数据,并为后续的日志管理奠定基础呢?
二 常用的方案有哪些?
方案一:表分区(推荐)
步骤:
-
确认表的结构和时间字段: 确保日记表中有一个用于时间的字段(例如
created_at
或date
),这是进行分区的基础。 -
备份数据: 在进行任何结构性更改之前,务必备份当前表以防止数据丢失。
mysqldump -u username -p your_database diary_table > diary_table_backup.sql
-
添加分区: 使用按月分区的方法。假设时间字段为
created_at
,可以使用以下SQL语句为表添加分区:ALTER TABLE diary_table PARTITION BY RANGE (TO_DAYS(created_at)) ( PARTITION p0 VALUES LESS THAN (TO_DAYS('2024-01-01')), PARTITION p1 VALUES LESS THAN (TO_DAYS('2024-02-01')), PARTITION p2 VALUES LESS THAN (TO_DAYS('2024-03-01')), ... PARTITION pN VALUES LESS THAN MAXVALUE );
注意:为每个月创建一个分区。可以根据具体需要调整分区策略。
-
删除旧分区: 一旦表被分区,可以通过丢弃早期的分区来快速删除大量数据,而无需逐行删除。
ALTER TABLE diary_table DROP PARTITION p0, p1, p2, ..., pM;
其中,
p0
到pM
代表要删除的旧月份分区。
优点:
- 高效:分区操作是元数据级别的,速度非常快。
- 维护简单:通过分区可以更方便地管理和查询数据。
缺点:
- 预先规划:如果表未分区,初次分区可能需要时间和资源。
- 复杂性增加:需要持续关注,在数据持续增长时,要为以后的时间节点手工增加分区。
方案二:创建新表并交换(适用已存有大量数据)
如果表当前未分区,且无法立即进行分区,可以考虑以下步骤:
步骤:
-
创建新表: 创建一个新的日记表,结构与原表相同,建议在创建时添加适当的索引以提高插入效率。
CREATE TABLE diary_table_new LIKE diary_table;
-
插入需要保留的数据: 将最近一个月的数据插入新表。可以使用
INSERT INTO ... SELECT
语句。INSERT INTO diary_table_new SELECT * FROM diary_table WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH);
注意:此步骤可能需要一些时间,具体取决于数据量和服务器性能。
-
重命名表: 为确保操作的原子性,使用
RENAME TABLE
进行表交换。RENAME TABLE diary_table TO diary_table_old, diary_table_new TO diary_table;
-
删除旧表: 确认新表数据无误后,删除旧表以释放空间。
DROP TABLE diary_table_old;
优点:
- 较快:相比逐行删除,创建新表并插入所需数据更快。
- 简单:操作步骤相对简单,易于执行。
缺点:
- 需要双倍存储空间:需要额外的存储空间来容纳新表。
- 短时间内锁定:在重命名表期间,可能会有短暂的表锁定,影响应用程序。
方案三:分批删除数据(定时任务实现)
如果上述方法不可行,可以考虑分批删除数据,以减少对数据库性能的影响。
步骤:
-
确定删除的时间范围: 例如,删除超过一个月的数据。
-
分批执行删除操作: 使用
DELETE
语句配合LIMIT
,逐步删除数据。DELETE FROM diary_table WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 MONTH) LIMIT 100000;
重复执行上述语句,直到满足删除条件。
-
优化删除过程:
- 禁用二级索引(如果适用):在删除前暂时禁用非必要的索引可以提高删除速度,删除后再重建索引。
- 监控事务日志大小:确保删除过程不会导致事务日志过大。
优点:
- 控制删除速度:避免一次性大量删除导致的性能问题。
- 灵活性:可以根据服务器负载调整删除批次大小和频率。
缺点:
- 耗时较长:相比直接删除,分批删除可能需要更长的时间完成全部删除操作。
- 复杂性增加:需要编写脚本或程序来自动化批量删除过程。
三 在线实战操作
当前状态不可能影在线业务,由于日志表主要是开发与运维查询问题时查看,只要保证数据不丢失即可,所以这里使用创建新表分区表比较合适。这个方案可以做到清理旧数据并保持系统稳定。
操作步骤:
1 创建分区表并迁移数据
如果你的原始日志表还没有分区,可以通过创建新表的方式实现按月分区。创建新表时,我们可以设计好分区结构,然后将旧表中的数据迁移到新表中。
-- 创建与原来结构一样的新表
CREATE TABLE ali_iot_log_n LIKE ali_iot_log;
创建表 如下图:
-- 为新表分区(按月份)ALTER TABLE ali_iot_log_n
PARTITION BY RANGE (TO_DAYS(ctime)) (PARTITION p0 VALUES LESS THAN (TO_DAYS('2024-01-01')),PARTITION p1 VALUES LESS THAN (TO_DAYS('2024-02-01')),PARTITION p2 VALUES LESS THAN (TO_DAYS('2024-03-01')),PARTITION p3 VALUES LESS THAN (TO_DAYS('2024-04-01')),PARTITION p4 VALUES LESS THAN (TO_DAYS('2024-05-01')),PARTITION p5 VALUES LESS THAN (TO_DAYS('2024-06-01')),PARTITION p6 VALUES LESS THAN (TO_DAYS('2024-07-01')),PARTITION p7 VALUES LESS THAN (TO_DAYS('2024-08-01')),PARTITION p8 VALUES LESS THAN (TO_DAYS('2024-09-01')),PARTITION p9 VALUES LESS THAN (TO_DAYS('2024-10-01')),PARTITION p10 VALUES LESS THAN (TO_DAYS('2024-11-01')),PARTITION p11 VALUES LESS THAN (TO_DAYS('2024-12-01')),PARTITION pp0 VALUES LESS THAN (TO_DAYS('2025-01-01')),PARTITION pp1 VALUES LESS THAN (TO_DAYS('2025-02-01')),PARTITION pp2 VALUES LESS THAN (TO_DAYS('2025-03-01')),PARTITION pp3 VALUES LESS THAN (TO_DAYS('2025-04-01')),PARTITION pp4 VALUES LESS THAN (TO_DAYS('2025-05-01')),PARTITION pp5 VALUES LESS THAN (TO_DAYS('2025-06-01')),PARTITION pp6 VALUES LESS THAN (TO_DAYS('2025-07-01')),PARTITION pp7 VALUES LESS THAN (TO_DAYS('2025-08-01')),PARTITION pp8 VALUES LESS THAN (TO_DAYS('2025-09-01')),PARTITION pp9 VALUES LESS THAN (TO_DAYS('2025-10-01')),PARTITION pp10 VALUES LESS THAN (TO_DAYS('2025-11-01')),PARTITION pp11 VALUES LESS THAN (TO_DAYS('2025-12-01')),PARTITION pN VALUES LESS THAN MAXVALUE
);
为表创建分区如下图:
2 旧表数据插入新表(重要)
然后将旧表中的需要保留的数据插入新表,这里一定要注意性能,查询条件尽量小批量进行,:
INSERT INTO ali_iot_log_n SELECT * FROM ali_iot_log WHERE ctime BETWEEN '2024-09-01 00:00:00' AND '2024-09-10 23:59:59';
我这边线上环境保存到数据库是使用队列,负责消费的处理保存的可以停下,数据都放在队列先,后面启动会继续使用,所以下面以条件10天数据量大概1亿条数据转存数据到新表,如下图:
每次迁移1亿条数据,分三次即可以1个月数据了,如果线上不间断运行保存就要考虑把最后某个时间点的数据不迁移先(可以改完表后再迁移) 。
3 重命名表,快速切换到新表
确认数据迁移完成,可以通过以下SQL实现旧表与新表的快速切换:
RENAME TABLE ali_iot_log TO ali_iot_log_old, ali_iot_log_n TO ali_iot_log;
该操作是原子性的,几乎不会影响业务的连续性,因为RENAME TABLE
是元数据操作,时间消耗极少,但是数据多的情况下还是需要几分钟时间,这里涉及30亿条数据量,如下图:
如果之前还有未迁完数据,迁完旧表即可。
迁移完后检查数据,确认没问题直接清空旧表即可
TRUNCATE TABLE ali_iot_log_old
4 定期删除旧分区数据
通过分区表管理日志后,删除旧数据变得非常简单。可以按月删除不再需要的分区,以释放存储空间。
比如删除1个月的数据,指定数据所在的分区即可:
ALTER TABLE ali_iot_log DROP PARTITION p0;
这比直接删除数据要高效得多,因为它只需要在元数据层面进行操作,避免了全表扫描和锁定。
操作建议
-
分批迁移数据
对于大型表的数据迁移操作,建议分批进行。可以通过LIMIT
关键字对数据进行分块插入,避免对数据库造成过大的压力。 -
选择低峰时段进行操作
大规模数据操作对性能有一定影响,建议在业务低峰时段进行操作,以最小化对用户的影响。 -
备份重要数据
在执行重大操作之前,建议对数据库进行备份。即便是删除旧数据或重命名表这样看似简单的操作,也应当做好应急恢复的准备。
四 总结
通过分区表的管理,可以极大提升MySQL在处理大规模日志表时的性能,特别是按时间维度划分分区后,数据的清理和查询将更加高效。结合重命名表和按月分区的方式,我们可以轻松应对日志表膨胀的问题,而不会对在线业务造成严重影响。
相关文章:

如何高效删除 MySQL 日志表中的历史数据?实战指南
在处理高并发的物联网平台或者其他日志密集型应用时,数据库中的日志表往往会迅速增长,数据量庞大到数百GB甚至更高,严重影响数据库性能。如何有效管理这些庞大的日志数据,特别是在不影响在线业务的情况下,成为了一项技…...

请散户股民看过来,密切关注两件大事
明天股市要开市,不仅散户股民期盼节后股市大涨,上面也同样想在节后来上一个“开门红”。 为此,上面没休假,关起门来办了两件大事,这两天发布消息已提前预热了。 两件大事如下: 一是,上交所10…...

设计模式之外观模式(Facade)
一、外观模式介绍 外观模式( Facade Pattern),也叫门面模式,是一个 “结构型” 设计模式。 外观模式的原始定义是:为子系统中的一组接口提供统一的接口。它定义了一个更高级别 的接口,使子系统更易于使用。 外观模式,是…...

解锁 Python 嵌套字典的奥秘:高效操作与实战应用指南
文章目录 前言🍀一、 什么是 Python 字典?1.1 字典的语法 🍀二、 字典的基本操作2.1 字典的创建2.2 访问字典中的值2.3 添加或修改键值对2.4 删除字典中的键值对 🍀三、 字典的遍历操作3.1 遍历字典的键3.2 遍历字典的值3.3 同时遍…...

联想服务器配置阵列、安装操作系统
文章目录 [toc]1.配置阵列2.制作启动盘3.安装系统 1.配置阵列 1.根据提示进入BIOS设置(F1) 2.系统设置 3.存储 4.第四步可以看到raid卡信息 5.Main Menu 6.Configuration Management 7.Create Virtual Drive 8.Select RAID Level raid5 9.Select Drives…...

【深度强化学习】DDPG实现的4个细节(OUNoise等)
文章目录 前言一、论文内容简述创新点(特点,与DQN的区别):可借鉴参数:细节补充: 二、细节1:weight_decay原理代码 三、细节2:OUNoise原理代码 四、细节3:ObsNorm原理代码…...

算法工程师重生之第二十二天(递增子序列 全排列 全排列 II 重新安排行程 N皇后 解数独 总结 )
参考文献 代码随想录 一、非递减子序列 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素,如出现两个整数相等,也可以视作…...

css的选择器及优先级
一、css选择器 CSS选择器是用来选择HTML文档中的元素,并为它们应用样式规则的工具。CSS选择器有很多种,可以根据元素的类名、ID、属性、伪类、伪元素、标签等来选择元素。以下是一些常见的CSS选择器及其用法: 1. ID选择器: 根据…...

JavaScript中的数组不改变原数组的方法
数组 var a [1, 2, 3, 5, 8, 13, 21] 不改变原数组的方法 length 数组元素的长度 继承自原型 concat(arrayX,arrayY) 合并两个或多个数组,返回新数组 合并,a.concat(b) var a[1,2,3],b[4,5,6],c[7,8,9]; a.concat(b,c); //[1, 2, 3, 4, 5, 6, 7…...

Go语言实现长连接并发框架 - 路由分组
文章目录 前言接口结构体接口实现项目地址最后 前言 你好,我是醉墨居士,我们上篇博客实现了任务执行流的路由模块,接下来我们实现一下对任务执行流进行任务 接口 trait/router_group.go type RouterGroup interface {RouterGroup(flow ..…...

跨 VLAN 通信
跨 VLAN 通信指的是不同 VLAN 之间的网络设备进行数据交换的能力。由于 VLAN 将网络分割成多个逻辑隔离的广播域,默认情况下,不同 VLAN 之间的设备无法直接通信。为了实现跨 VLAN 通信,需要借助一些网络设备和技术。以下详细讲解跨 VLAN 通信…...

11.4 Linux_线程_条件变量
概述 条件变量的作用: 条件变量和互斥量配合使用,主要应用于生产者和消费者问题。 这种问题也是一种临界资源的问题,但与互斥量一文中 "写文件" 这种资源不同。文件是一直存在的临界资源,而生产者的资源不是一直存在…...

通信工程学习:什么是IP网际协议
IP:网际协议 IP网际协议(Internet Protocol,简称IP)是整个TCP/IP协议栈中的核心协议之一,它负责在网络中传送数据包,并提供寻址和路由功能。以下是对IP网际协议的详细解释: 一、对IP网际协议的…...

github 国内文件加速下载
参看;https://www.cnblogs.com/ting1/p/18356265 在源网址前加上 https://hub.gitmirror.com/ 或https://mirror.ghproxy.com/,例如: https://hub.gitmirror.com/https://github.com/t1m0thyj/WinDynamicDesktop/releases/download/v5.4.1/WinDynamicD…...

算法6:模拟运算
文章目录 z字形变幻外观数列数青蛙 题目均来自于力扣 z字形变幻 class Solution { public:string convert(string s, int numRows) {int n s.size();if(n < numRows || numRows 1) return s;int d 2 * numRows - 2;string res;for(int j 0; j < n; j d){res s[j]; …...

【网络协议大花园】应用层 http协议的使用小技巧,用好了都不用加班,效率翻两倍(上篇)
本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…...

今日指数day8实战补充(上)
1.用户管理 1.多条件综合查询 1.1 多条件综合查询接口说明 1)原型效果 2)接口说明 功能描述:多条件综合查询用户分页信息,条件包含:分页信息 用户创建日期范围 服务路径:/api/users 服务方法࿱…...

Python 之进阶语法:with...as...
1. Python with…as…是什么 Python 的 with…as… 语句,就像一个贴心的管家,负责照顾你的资源,让你不再担心忘记关闭文件、网络连接或数据库事务等。这个管家在你进入“房间”时自动打开门,离开时帮你把门关上,真的是…...

嵌入式硬件设计知识详解
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

计算机网络:物理层 —— 信道及其极限容量
文章目录 信道信道的极限容量信号失真失真类型产生信号失真的主要因素 奈式准则码元传输速率香农公式 信道 信道是指信息传输的通道或介质。在通信中,信道扮演着传输信息的媒介的角色,将发送方发送的信号传递给接收方。 信道可以是无线信道,…...

面向对象特性中 继承详解
目录 概念: 定义: 定义格式 继承关系和访问限定符 基类和派生类对象赋值转换: 继承中的作用域: 派生类的默认成员函数 继承与友元: 继承与静态成员: 复杂的菱形继承及菱形虚拟继承: 虚…...

C++ | Leetcode C++题解之第455题分发饼干
题目: 题解: class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int m g.size(), n s.size();int count 0;for (int i 0, j 0; i < …...

java版基于Spring Boot + Mybatis在线招投标|评标|竞标|单一采购|询价|邀标|在线开标|招标公告发布|评审专家|招投标采购系统源码
一、项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,…...

Anaconda的安装与环境设置
文章目录 一、Anaconda介绍二、Anaconda环境搭建1. 下载Anaconda(1)官网下载(2)清华大学镜像 2. 安装Anaconda3.配置环境变量4.检验conda是否安装成功5.更改镜像源6.若菜单栏没有conda prompt 三、虚拟环境1.创建、查看、删除虚拟环境2.激活、退出虚拟环境 四、CUDA、Pytorch、…...

使用FastAPI做人工智能后端服务器时,接口内的操作不是异步操作的解决方案
在做AI模型推理的接口时,这时候接口是非异步的,但是uvicorn运行FastAPI时就会出现阻塞所有请求。 这时候需要解决这个问题: api.py: import asyncio from fastapi import FastAPI from fastapi.responses import StreamingResp…...

Leetcode 3312. Sorted GCD Pair Queries
Leetcode 3312. Sorted GCD Pair Queries 1. 解题思路2. 代码实现 题目链接:3312. Sorted GCD Pair Queries 1. 解题思路 这一题的话坦率来说没有搞定,后来是找的大佬的代码抄了一下…… 整体来说这道题思路上还是比较暴力的,还是一个二重…...

用 Delphi 做了一个简单的 CMS
Delphi 代码上面花的时间最少。 前提是你要熟悉 Delphi 的 WebBroker 框架。不熟悉也没关系,5分钟就可以入门,10分钟就熟悉了。 CMS 就是个基于 WEB 的内容管理嘛。相当于一个简单的没有跟贴功能的 BBS。这样的东西,后边是数据库࿰…...

ASK, PSK, FSK, DPSK
ASK, PSK, FSK, DPSK详解: 这四种调制方式都是数字调制技术,用于将数字信号转换成适合在信道上传输的模拟信号。它们的主要区别在于如何用模拟信号的变化来表示数字信息。 1. ASK (Amplitude Shift Keying) 幅移键控: 原理: ASK 通过改变载波信号的幅…...

【Linux】认识Linux内核中进程级别的文件结构体【files_struct】&文件IO模型初步演示
前言 大家好吖,欢迎来到 YY 滴 系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! YY的《C》专栏YY的《C11》专栏YY的《Linux》…...

[Offsec Lab] ICMP Monitorr-RCE+hping3权限提升
信息收集 IP AddressOpening Ports192.168.52.218TCP:22,80 $ nmap -p- 192.168.52.218 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 de:b5:23:89:bb:9f:d4:1…...