我有一个密码恢复系统,允许用户通过电子邮件恢复密码。每个请求的详细信息都插入到我的recoveries
表中,并在成功恢复后删除。我有每个恢复的时间戳,它是在创建每个恢复后10分钟设置的。
我想实现一个系统,它将在10分钟后自动删除每个过期的恢复。由于每一行的到期时间都不同,这意味着使用cron作业在执行此任务时会非常无效。
实现这一目标的最有效方法是什么?
这是我的代码:
$time = time();
$recoveries = DB::fetch("DELETE FROM `recoveries` WHERE `expiry` <= ?;", array($time));
最有效的方法是使用视图。嗯?这和问题有什么关系?好吧,不要在病房10分钟后删除。相反,创建一个具有以下逻辑的视图:
create view v_recoveries as
select r.*
from recoveries r
where expiry > date_sub(now(), interval 10 minutes);
为了提高性能,您需要recoveries(expiry)
上的索引,所以这应该很快。
然后,在你空闲的时候——每天一次,每小时一次,或每周一次——用删除不需要的记录
DELETE FROM `recoveries`
WHERE `expiry` <= date_sub(now(), interval 10 minutes);
这种方法有几个优点:
- 数据的存在时间正好是10分钟,而不是基于某些作业的调度
- 实际删除可能发生在系统静止时
- 如果cron作业无法执行,则数据不会"损坏"——也就是说,不会得到太旧的数据
- 如果系统繁忙(大量插入),则插入不会与删除竞争,从而进一步降低系统速度
您可以在mysql级别编写一个触发器函数,当插入/更新条目时,它将触发该函数,该函数将删除该特定用户的所有条目(或早于10分钟的条目)。这样你就不必每1分钟检查一次(cron作业)就可以看到要从数据库中删除的条目(这将使你的生活变得轻松,并节省一些资源)
您也可以在任何人登录时实现此技术(如果您不想在mysql级别使用触发器)