需求:定时删除三个月之前的数据

1.编写需要执行的sql语句

1
2
3
4
5
6
7
8
9
10
11
12
## 因为表数据过大(大约2亿数据),需要先查询三个月之前的id节点,增加查询速度
select MAX(id) from other_log_info where DATE_FORMAT(createtime,'%Y-%m-%d') = DATE_SUB(CURDATE(),INTERVAL 3 MONTH);

## 查询的sql一次不能删除太多数据,防止锁表
select * from other_log_info where id < (select MAX(id) from other_log_info where DATE_FORMAT(createtime,'%Y-%m-%d') = DATE_SUB(CURDATE(),INTERVAL 3 MONTH)) LIMIT 0,1000

## 由于delete不能直接删除子查询表中的数据,必须用过嵌套一层的方式来解决
## 第二种执行方式,如果对于sql比较熟悉,可以用存储过程的"游标"进行循环
DELETE FROM other_log_info where id in
(select t2.id from
(select id from other_log_info where
id < (select MAX(id) from other_log_info where createtime < DATE_SUB(CURDATE(),INTERVAL 3 MONTH)) LIMIT 0,1000) t2)

游标使用方式:https://www.cnblogs.com/cbt-home/p/15269736.html

  • CURDATE() 返回当前日期
  • CURNOW() 返回当前datetime
  • INTERVAL 是mysql间隔值,用法为INTERVAL expr unit。INTERVAL 3 DAY表示三天的间隔
  • DATE_SUB(start_date,INTERVAL expr unit);

2.编写存储过程

存储过程相当于mysql的函数,它是存储在数据库服务器中的一组sql语句,通过调用这个函数的名称来执行这些sql语句命令。

1
2
3
4
5
6
7
8
-- 分隔符切换防止“;”直接分隔了
DELIMITER //
-- 创建存储过程
CREATE procedure del_log2()
BEGIN
SELECT * FROM xxl_job_log WHERE trigger_time < DATE_SUB(CURDATE(),INTERVAL 5 MONTH);
END //
DELIMITER ;
  • DELIMITER是分割符的意思,声明存储过程前将"//"声明为分隔符,这样存储过程中的“;”才不会被当作分隔符处理。声明结束后再还原分隔符。
  • 存储过程也可以带参数,存储过程名(参数)
  • 在声明存储过程前要先用use database_name切换到想要应用的数据库,否则存储过程会应用到默认数据库中

查看存储过程

1
2
-- db指的数据库名
select * from mysql.proc where db = "xxl_job"

调用存储过程

1
call del_log();

3.编写事件调度器(定时任务)

1
2
3
4
5
-- 确认是否开启事件调度器
SHOW VARIABLES LIKE 'event_scheduler';

-- 开启事件调度器
SET GLOBAL event_scheduler = ON;

创建事件

1
2
3
4
5
6
-- 创建调度任务(从2022-4-22开始,每天执行一次del_data())
create event del_event
on schedule
EVERY 1 day
STARTS '2022-4-22 00:00:00'
do call del_data()

查看事件

1
2
-- 查看事件
SHOW EVENTS;

image-20220422104326667

image-20220422104354508

image-20220422104419241