日期:2014-05-16  浏览次数:20924 次

(转)用mysql的存储过程和event来做计划任务
http://aiyooyoo.com/index.php/archives/298/
我在第一章提到过CLI的执行是不限时的,所以你可以用它来做计划任务。也就是在未来的某个时间自动执行某个任务。网页的话,可以这么来
<?Php
ignore_user_abort(true);
set_time_limit(0);
if(date("m")%5==0){
//do something}
    加入ignore_user_abort(true)是为了保证用户在关闭了网页后,程序不会立即中断,而是在后台执行。计划任务的触发可以由用户或蜘蛛来触发,也可以对某些任务采取伪任务的方式(即若任务没有被外界触发,那么在后台查看任务时,先标记任务为已执行,然后再触发慢慢地去执行。因为很多任务的实时性并不高)。如果是unix系操作系统的话,则用crontab这款工具来执行。如果是涉及到单纯的数据库操作的话,则可以由mysql5.1的event来定时触发。这样比用php来的更直接。既然是数据库操作,我为啥不直接用mysql呢?何必再php调mysql多此一举?下面我举个例子,顺带介绍下mysql里的存储过程和定时器。
比如,我有个需求,需要定期删除已被处理过的log,而这些log存储在数据库里,表结构如下:


CREATE TABLE `log` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`message` VARCHAR(200) NULL DEFAULT '0',
`isread` INT(11) NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
我现在需要定期删除已经看过的日志文件,我先写个存储过程
DELIMITER //
CREATE PROCEDURE `utable`(IN `$tname` VARCHAR(20),IN $field varchar(10))
BEGIN
SET @sqlcmd = CONCAT("delete from ",$tname," where ",$field,"=1");
PREPARE stmt FROM @sqlcmd;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
//
这个存储过程的调用如下:CALL `utable`('log', 'isread'),基于此,我创建一个事件:
CREATE EVENT IF NOT EXISTS event_log
ON SCHEDULE EVERY 100 SECOND
ON COMPLETION PRESERVE
DO CALL `utable`('log', 'isread');
    这个event的含义是每100秒执行一次,调用上面存储过程,当然了,你可以根据需求定制执行间隔。事件一旦创建,就会自动执行。你可以事先在log表里插入一些数据,过100秒后看看是不是符合条件的数据都被删除了呢?要关闭event,请用此语句:ALTER EVENT event_log ON  COMPLETION PRESERVE DISABLE; 如果你用的是我推荐的mysql管理工具heidisql,那么管理起来更方便,点点鼠标就行了。用navicat也不错。当然了,你会说,这个没必要这么麻烦吧?php来做很简单啊。但是你想想,对于更精确的需求,单纯依靠php脚本能保证精确定时执行否?效率呢?其实这个主要用于队列服务。在用mysql来模拟队列的时候,就需要用到存储过程,定时器等工具。而这在SNS,微博类的应用中是很常见,也是最简单的方式。
    如果你创建的event执行不了,可能是你的mysql没有打开event功能,此功能默认是关闭的。查看是否打开:SHOW VARIABLES LIKE '%sche%'; 打开event功能:SET GLOBAL event_scheduler = 1;