轮询MySQL表以获取新行的最快方法是什么?

时间:2010-09-08 06:44:35

标签: php mysql triggers polling

我的应用程序需要轮询MySQL数据库以获取新行。每次添加新行时,都应检索它们。我正在考虑创建一个触发器,以在单独的表上放置对新行的引用。原始表有超过300,000行。

该应用程序是用PHP构建的。

一些好的答案,我认为这个问题应该得到赏金。

7 个答案:

答案 0 :(得分:7)

对于外部应用程序,我发现使用TimeStamp列是一种更健壮的方法,它独立于自动ID和其他主键问题

向表中添加列,例如:

insertedOn TIMESTAMP DEFAULT CURRENT_TIMESTAMP

或跟踪插入和更新

updatedOn TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

在外部应用程序中,您只需跟踪执行轮询时的上一个时间戳。然后从所有相关表上的时间戳中选择。在大型表中,您可能需要索引时间戳列

答案 1 :(得分:3)

您可以使用以下语句查明表中是否插入了新记录:

select max(id) from table_name

在上面的语句中替换主键和表名的名称。将max(id)值保存在临时变量中,并检索此值与上次保存的max(id)值之间的所有新记录。获取新记录后,将max(id)值设置为您从查询中获得的值。

答案 2 :(得分:1)

创建一个PHP守护进程来监视MySQL表文件大小,如果大小更改查询新记录,如果发现新记录运行下一个进程。

我认为有一个活动的PEAR守护程序,您可以轻松配置以监视MySQL表文件大小并启动​​脚本。

答案 3 :(得分:0)

假设您有一个标识或其他一些总是增长的数据,您应该跟踪您的php应用程序中检索到的最后一个ID。

这适用于大多数情况。除非你进入实时营地,否则我认为你不需要更多。

答案 4 :(得分:0)

我会做这样的事情。当然,这是假设ID是递增的数字ID。 以及如何将“当前位置”存储在数据库中是最重要的。

<?
$idFile = 'lastID.dat';

if(is_file($idFile)){
    $lastSelectedId = (int)file_get_contents($idFile);
} else {
    $lastSelectedId = 0;
}

$res = mysql_query("select * from table_name where id > {$lastSelectedId}");

while($row = mysql_fetch_assoc($res)){
    // Do something with the new rows

    if($row['id']>$lastSelectedId){
        $lastSelectedId = $row['id'];
    }
}

file_put_contents($idFile,$lastSelectedId);

?>

答案 5 :(得分:0)

我会同意TFD关于在单独的文件/表中跟踪时间戳然后获取比这更新的所有行的答案。这就是我为类似的应用程序做的。

您的应用程序查询单行表(或文件)以查看时间戳是否已从本地存储更改,这不应该是性能损失。然后,假设时间戳被正确编入索引,那么基于时间戳从300k行表中获取新行应该再次正常。

然而,阅读你的问题我很好奇,如果Mysql触发器可以进行系统调用,比如一个PHP脚本会做一些繁重的工作。使用they can sys_exec()结果显示User-Defined Function。您可以使用它来执行各种处理,方法是将插入的行数据传递给它,基本上有插入的即时通知。

最后,a word of caution关于使用触发器来调用外部应用程序。

答案 6 :(得分:0)

一个选项可能是使用INSERT INTO SELECT语句。从使用时间戳的建议中提取最新的行,您可以执行类似......

的操作
INSERT INTO t2 (
    SELECT * 
    FROM t1 
    WHERE createdts > DATE_SUB(NOW(), INTERVAL 1 HOUR)
);

这将占用前一小时插入的所有行,并将它们插入到表2中。您可以让脚本运行此查询并让它每小时运行一次(或者您需要的任何时间间隔)。

这将大大简化您的PHP脚本以提取行,因为您不需要迭代任何行。它还摆脱了必须跟踪最后一个插入ID。

Fanis的解决方案也听起来也很有趣。

作为注释,上面插入的select查询可以调整为仅插入某些字段。如果您只需要某些字段,则需要在插入中指定它们,如此...

INSERT INTO t2 (field1, field2) (
    SELECT field1, field2 
    FROM t1 
    WHERE createdts > DATE_SUB(NOW(), INTERVAL 1 HOUR)
);