这类问题已经发布了几次,但在以下情况下提供的解决方案并不理想。在第一个查询中,我正在选择执行第一个查询时我知道存在的表名。然后在循环遍历它们时,我想查询所选表中的记录数,但前提是它们仍然存在。问题是,在循环期间,一些表被另一个脚本删除。例如:
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运行的,它失败了fataly,我收到了来自cron的电子邮件,说它失败了。
DBD :: mysql :: st执行失败:表'xxx'不存在于 /usr/local/lib/perl/5.10.1/Mysql.pm第175行。
脚本正在使用已弃用的Mysql.pm perl模块。
答案 0 :(得分:1)
显然,您需要保护表以确保在执行查询之前不会删除它。请记住,如果您从某种表锁开始,为了避免可能的丢失 - 从其他地方发出的DROP TABLE查询将失败并出现一些锁错误,或者至少会等到SELECT完成。删除表并不常用于操作,因此在大多数情况下,架构设计在服务器操作期间仍然存在 - 您观察到的是非常罕见的行为。通常,不支持在其他查询期间阻止表被删除,但是,在下面文档的注释中,您可能会发现使用信号量表来实现它的一些技巧。
http://dev.mysql.com/doc/refman/5.1/en/lock-tables.html
“表锁仅保护其他会话不被不适当的读取或写入。持有锁的会话,甚至是读锁,都可以执行表级操作,例如DROP TABLE。截断操作不是事务安全的,所以如果会话在活动事务期间或在持有表锁时尝试一个会发生错误。“
“如果您需要对通常不受读取或写入锁定(例如删除或截断表格)的表格执行操作,并且您能够合作,则可以尝试以下操作:使用信号量表,并创建两个每个进程的会话。在第一个会话中,根据需要在信号量表上获取读或写锁。在第二个会话中,执行所有其他表所需的操作。“
答案 1 :(得分:1)
您应该能够通过将其置于eval块中来保护您的perl代码失败。这样的事情:
eval {
# try doing something with DBD::mysql
};
if ($@) {
# oops, mysql code failed.
# probably need to try it again
}
甚至把它放在“while”循环中
如果您使用像Postgres这样的更好的服务器,那么正确的解决方案就是将所有内容都包含在事务中。但是,在MySQL中,丢弃表不受事务保护。