4

此类问题已发布过几次,但提供的解决方案在以下情况下并不理想。在第一个查询中,我选择在执行第一个查询时我知道存在的表名。然后在遍历它们时,我想查询所选表中的记录数,但前提是它们仍然存在。问题是,在循环期间,一些表被另一个脚本删除。例如 :

SELECT tablename FROM table
-- returns say 100 tables

while (%tables){
    SELECT COUNT(*) FROM $table
    -- by the time it gets to the umpteenth table, it's been dropped
    -- so the SELECT COUNT(*) fails
}

而且,我猜是因为它是由 cron 运行的,所以它失败了,并且我收到了一封来自 cron 的电子邮件,说明它失败了。

DBD::mysql::st 执行失败:/usr/local/lib/perl/5.10.1/Mysql.pm 第 175 行不存在表 'xxx'。

脚本正在使用已弃用的 Mysql.pm perl 模块。

4

2 回答 2

1

您应该能够通过将其放入 eval 块来保护您的 perl 代码免于失败。像这样的东西:

eval {
    # try doing something with DBD::mysql
};
if ($@) {
    # oops, mysql code failed.
    # probably need to try it again
}

甚至把它放在“while”循环中

如果您使用像 Postgres 这样更好的服务器,正确的解决方案是将所有内容都包含在事务中。但是,在 MySQL 中删除表不受事务保护。

于 2012-10-16T07:05:37.983 回答
1

显然,您需要保护表以确保在执行查询之前它不会被删除。请记住,如果您从某种表锁开始,为了避免可能的丢弃 - 从其他地方发出的 DROP TABLE 查询将因某些锁错误而失败,或者至少会等到您的 SELECT 完成。删除表并不是真正经常使用的操作,因此在大多数情况下,架构设计在服务器操作期间仍然存在 - 您观察到的行为非常罕见。通常,不支持在其他查询期间防止表被删除,但是,在下面文档的注释中,您可能会发现使用信号量表来实现它的一些技巧。

http://dev.mysql.com/doc/refman/5.1/en/lock-tables.html

“表锁只保护其他会话不适当的读取或写入。持有锁的会话,即使是读取锁,也可以执行表级操作,例如 DROP TABLE。截断操作不是事务安全的,因此如果发生错误,则会发生错误会话在活动事务期间或在持有表锁时尝试一次。”

“如果您需要对通常不受读或写锁支持的表执行操作(例如删除或截断表),并且您能够合作,您可以尝试以下操作:使用信号量表,并为每个进程创建两个会话. 在第一个会话中,酌情在信号量表上获得一个读或写锁。在第二个会话中,对所有其他表执行您需要做的所有事情。

于 2012-10-16T06:54:24.773 回答