我的应用程序需要轮询MySQL数据库以获取新行。每次添加新行时,都应检索它们。我正在考虑创建一个触发器,以在单独的表上放置对新行的引用。原始表有超过300,000行。
该应用程序是用PHP构建的。
一些好的答案,我认为这个问题应该得到赏金。
答案 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)
);