2012-10-16 65 views
4

这种类型的问题已发布几次,但提供的解决方案在以下情况下并不理想。在第一个查询中,我选择了在执行第一个查询时存在的表名。然后在遍历它们的同时,我想查询选定表格中的记录数量,但前提是它们仍然存在。问题是,在循环过程中,一些表被另一个脚本丢弃。例如:mysql非本机,仅当表存在时才选择

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

异常处理??? – Khaleel

+0

新用户提示:如果您发现它有用,您可以upvote /接受一些答案。你应该包括你的问题涉及的mysql引擎版本。 –

+1

你尝试使用交易吗? –

回答

1

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

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

“表锁只能预防不当读取或由其他会话写道。会话持有锁,甚至读锁,可以执行表级的操作,比如DROP TABLE。截断操作不事务安全,所以如果会话在活动事务期间或持有表锁定时尝试一个错误,则会发生错误。“ “如果您需要对通常不受读或写锁定支持的表执行操作(如删除或截断表),并且您可以配合使用,则可以尝试以下操作:使用信号量表并创建每个进程有两个会话在第一个会话中,根据需要在信号量表上获得一个读或写锁定,在第二个会话中,完成所有其他表的操作。

+0

这听起来像它正是我需要的。存储引擎是MyISAM,Mysql版本是:5.0.95。我如何将它锁定在初始查询中,然后在完成后解锁它?我现在会对此进行一些研究。谢谢。 – user1749141

+0

看起来像它可能只适用于本机SQL代码。我正在使用Mysql perl模块。 – user1749141

1

你应该能够通过将它放入eval块来保护你的perl代码免于失败。类似的东西:

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

甚至把这个“while”循环

如果你喜欢使用的Postgres更好的服务器,正确的解决方案将封闭一切都变成交易。但是,在MySQL丢弃表中不受事务保护。

+0

它是在while循环中,这是问题,当它循环(每次迭代需要一两秒钟)时,表将被另一个脚本删除。 Innodb引擎的最新版本也支持事务。当我醒来的时候会试试eval。通常使用类似于:if($ dbh-> execute)陷阱错误,但cron版本正在死亡。 – user1749141

+0

Eval也没有接受它。仍然得到cron notifs。 Cron命令是:*/1 * * * * /x.cgi 2>&1>/dev/null – user1749141

+0

您应该能够将原始选择的结果与表名称存储在数组或散列中。然后遍历目标表的列表以执行“SELECT count(*)FROM tableN”。但是,当做这个声明时,把它放入eval块。这应该肯定工作 - 克朗与否。要进行调试,可以手动将垃圾名称放到目标表的列表中,以检查脚本是否在这些表上发出嘘声 – mvp

相关问题