mysql - 如何检查数据库中的记录数是否超过 x 次

标签 mysql sql perl

我有一个 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/

相关文章:

sql - 工会异常行为

python - 如何使用 sqlalchemy 截断和插入同一事务?

sql - 在 SQL Server 中将用户定义的表类型与临时存储过程一起使用

java - 声明关闭问题后不允许进行任何操作

perl - 使用 Perl 并发追加到同一个文件

perl - 如何在 Win32 上使用 Perl 重新映射键盘?

html - Perl解析html后出现未初始化值错误

php - 如何从 mysql 数据库获取 xmlrpc 响应,如字段名称作为元素和记录作为数据?

PHP/SQL 数据库查询的良好实践和安全性

php - XEditable 使用 PHP MySQL 通过 Ajax 更新 : issue with updating different columns.