我有一个 MySQL 表,它按照以下方案保存记录:
hostname | appname | timestamp | message
我正在使用 perl 脚本查询数据库以获取最后一分钟的所有记录。此脚本每 60 秒激活一次。
Perl 脚本收集时间戳大于当前时间戳的所有记录 - 60 秒。 然后我可以检查我是否有超过(比方说 5)条记录让我在脚本中做一些其他事情。
我想要实现的是在我的脚本中有一种“窗口”,能够查看每 60 秒脚本激活之间是否存在重叠,以确保可能还有超过 5 条记录。
我举个例子:
脚本在 08:42:00 执行,收集从 08:41:00 到开始时间的所有记录:
foo.net spbx 16-06-2014 08:41:51
foo.net spbx 16-06-2014 08:41:55
foo.net spbx 16-06-2014 08:41:57
foo.net spbx 16-06-2014 08:42:59
所以它的 4 条记录 - 无关。
在 08:43:00 执行的脚本从 08:42:00 到开始时间:
foo.net spbx 16-06-2014 08:42:01
foo.net spbx 16-06-2014 08:42:02
foo.net spbx 16-06-2014 08:42:03
foo.net spbx 16-06-2014 08:42:04
仍然没有错误。但是,如果您精确地观察到 60 秒的“动态间隔”,那么您会在 60 秒的间隔内发生 5 个以上的事件,而这种简单方法看不到这一点。
我考虑总是收集最后 120 秒的数据,然后在 60 秒的窗口中从最旧的条目向上检查是否有超过 5 个事件。但我想知道是否有更好的方法来解决这个“问题”?
进一步思考,如果这种动态方法发现超过 5 个事件,那么它需要删除这些条目,以便在下一次执行时不收集它们(或者只是在数据库中标记它们)
当前代码部分如下:
my $dbConnect = DBI->connect("DBI:mysql:database=$dbName;host=$dbHost","$dbUser","$dbPass", { RaiseError => 1, AutoCommit => 0})
or die "ERROR - Can't connect to MySQL-Database: ".$DBI::errstr."\n";
debug("Connect to database successfull");
my $dbQuery = $dbConnect->prepare("SELECT message,timestamp FROM $dbTable WHERE hostname='$hostname' AND appname='$appname' AND timestamp > ?");
my $date = Time::Piece->strptime(localtime->epoch-$threshold[1],"%s");
# adding the timezone offset - workaround for FAP-CENTREON
$date += $date->localtime->tzoffset;
my $starttime = $date->strftime("%Y-%m-%d %H:%M:%S");
debug("query: SELECT message,timestamp FROM $dbTable WHERE hostname=$hostname AND appname=$appname AND timestamp > ".$starttime);
$dbQuery->execute($starttime);
my $amount = $dbQuery->rows;
$alarmMessage = "$amount errors in ".$threshold[1]."s!\n";
if($amount < $threshold[0]) {
$alarmMessage = "$amount errors in ".$threshold[1]."s - this is OK! \n";
$exitCode = 0;
} else {
while(my @resultrows = $dbQuery->fetchrow_array) {
$alarmMessage = $alarmMessage.$resultrows[1]." ".$resultrows[0]."\n";
}
$exitCode = 2;
}
$dbQuery->finish();
$dbConnect->disconnect();
print "$alarmMessage \n";
最佳答案
您可以使用单个查询完成第一部分:
SELECT a.timestamp, COUNT(*) ct
FROM $dbTable AS a
JOIN $dbTable AS b ON b.timestamp BETWEEN a.timestamp AND DATE_ADD(a.timestamp, INTERVAL 1 MINUTE)
WHERE a.timestamp > DATE_SUB(NOW(), INTERVAL 2 MINUTE)
GROUP BY a.timestamp
HAVING ct > 5
要找到应该删除或标记为已被注意为多余的消息,您可以将此子查询连接到表中并选择时间戳后 1 分钟内的所有消息。
关于mysql - 如何检查数据库中的记录数是否超过 x 次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24238014/