-- 删除旧事件(如果存在)
DROP EVENT IF EXISTS delete_expired_captchas;
-- 创建新事件(每分钟执行一次)
CREATE EVENT delete_expired_captchas
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP
COMMENT '每分钟清理过期验证码'
DO
DELETE FROM captcha
WHERE created_at < NOW() - INTERVAL 10 MINUTE;
数据库本身没有直接的「自动删除过期数据」的功能,但可以通过以下两种方式模拟实现:
Event Scheduler
):定期执行删除过期数据的SQL语句。默认情况下,MySQL的事件调度器是关闭的。需在配置文件中启用:
-- 检查事件调度器状态
SHOW VARIABLES LIKE 'event_scheduler';
-- 启用事件调度器(临时生效)
SET GLOBAL event_scheduler = ON;
-- 永久生效需修改配置文件 my.cnf:
[mysqld]
event_scheduler = ON
创建一个每天自动清理过期验证码的事件:
CREATE EVENT delete_expired_captchas
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP
DO
DELETE FROM captcha
WHERE created_at < NOW() - INTERVAL 10 MINUTE;
-- 查看事件状态
SHOW EVENTS;
-- 手动触发事件(测试用)
CALL delete_expired_captchas;
在验证验证码时,检查时间差并删除过期记录:
@Service
public class DatabaseCaptchaService {
@Autowired
private JdbcTemplate jdbcTemplate;
public boolean validateCaptcha(String key, String userInput) {
// 查询验证码及生成时间
String sql = "SELECT code, created_at FROM captcha WHERE id = ?";
return jdbcTemplate.query(sql, (rs) -> {
if (rs.next()) {
String storedCode = rs.getString("code");
Timestamp createdAt = rs.getTimestamp("created_at");
long age = System.currentTimeMillis() - createdAt.getTime();
if (age > 10 * 60 * 1000) { // 超过10分钟
// 删除过期记录
jdbcTemplate.update("DELETE FROM captcha WHERE id = ?", key);
return false;
}
return storedCode.equals(userInput);
}
return false;
}, key);
}
}
结合两种方式实现高可靠性:
pg_cron
扩展或定时任务工具(如cron
)实现类似功能。SQL Server Agent
创建定时作业。 特性 |
数据库方案 |
Redis方案 |
自动删除 |
需配置事件调度器或应用层逻辑 |
内置TTL,自动删除 |
实时性 |
依赖清理频率(非实时) |
实时删除 |
性能 |
高频清理可能影响性能 |
高性能,无额外开销 |
适用场景 |
无Redis环境或低频验证码场景 |
高并发、实时性要求高的场景 |
可以通过数据库实现验证码的自动删除,但需权衡实时性和性能。
关键代码示例:
-- 创建每日清理事件(MySQL)
CREATE EVENT delete_expired_captchas
ON SCHEDULE EVERY 1 DAY
DO
DELETE FROM captcha
WHERE created_at < NOW() - INTERVAL 10 MINUTE;
-- 创建一个每天自动清理过期验证码的事件: CREATE EVENT delete_expired_captchas ON SCHEDULE EVERY 1 DAY STARTS CURRENT_TIMESTAMP DO DELETE FROM captcha WHERE created_at < NOW() - INTERVAL 10 MINUTE;10分钟没生效。原因排查
以下是分步说明,确保事件每天自动执行并持续生效:
执行以下SQL命令检查事件调度器状态:
SHOW VARIABLES LIKE 'event_scheduler';
如果结果为 OFF
,需启用调度器:
永久生效需修改MySQL配置文件(如 my.cnf/my.ini
):
[mysqld]
event_scheduler = ON
修改后重启MySQL服务。
原事件设置为每天执行一次(EVERY 1 DAY
),但过期验证码需在生成10分钟后删除,因此需提高执行频率。
推荐方案:每分钟执行一次(实时清理):
-- 删除旧事件(如果存在)
DROP EVENT IF EXISTS delete_expired_captchas;
-- 创建新事件(每分钟执行一次)
CREATE EVENT delete_expired_captchas
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP
COMMENT '每分钟清理过期验证码'
DO
DELETE FROM captcha
WHERE created_at < NOW() - INTERVAL 10 MINUTE;
查看事件列表:
ENABLED
。手动触发测试:
权限要求:用户需具备 EVENT
权限。授权命令:
如果数据库时区与系统时区不一致,可能导致时间计算错误。
查看当前时区:
设置时区(例如设为东八区):
SET GLOBAL time_zone = '+8:00';
SET time_zone = '+8:00';
查看MySQL错误日志(路径通常在 /var/log/mysql/error.log
):
Event Scheduler
相关记录,表示事件正在运行。插入测试数据:
INSERT INTO captcha (id, code, created_at)
VALUES ('test', '123456', NOW() - INTERVAL 11 MINUTE);
等待1分钟后检查数据:
通过以上步骤,事件将每分钟执行一次,确保所有超过10分钟的验证码被实时清理。
关键点: