在perl中杀死mysql查询

时间:2010-12-26 15:56:17

标签: mysql perl dbi

我有一个perl脚本,我在其中创建一个来自现有mysql数据库的表。我在每个数据库中有数百个数据库和表包含数百万条记录,因此,有时,由于索引问题,查询需要数小时,有时由于连接不当而耗尽磁盘空间。有没有办法可以在同一个脚本中查看查询以查看内存消耗和执行时间?

P.S。我在perl中使用DBI模块用于mysql接口

3 个答案:

答案 0 :(得分:2)

我使用了http://www.perlmonks.org/?node_id=885620

中描述的KILL QUERY命令

这是我脚本中的代码

eval {
    eval { # Time out and interrupt work
        my $TimeOut=Sys::SigAction::set_sig_handler('ALRM',sub {
            $dbh->clone()->do("KILL QUERY ".$dbh->{"mysql_thread_id"});
            die "TIMEOUT\n";
        });
        #Set alarm
        alarm($seconds);
        $sth->execute();
        # Clear alarm
        #alarm(0);
    };
    # Prevent race condition
    alarm(0);
    die "$@" if $@;
};

此代码会终止查询并删除所有临时表

答案 1 :(得分:1)

就执行时间而言,您使用alarm Perl功能超时。

您的ALRM句柄可以die(请参阅下面的示例),也可以发出DBI cancel来电(sub { $sth->cancel };

DBI documentation实际上对此以及示例进行了非常好的讨论:

  eval {
    local $SIG{ALRM} = sub { die "TIMEOUT\n" }; # N.B. \n required
    eval {
      alarm($seconds);
      ... code to execute with timeout here (which may die) ...
    };
    # outer eval catches alarm that might fire JUST before this alarm(0)
    alarm(0);  # cancel alarm (if code ran fast)
    die "$@" if $@;
  };
  if ( $@ eq "TIMEOUT\n" ) { ... }
  elsif ($@) { ... } # some other error

就观察内存而言,您只需要ALRM处理程序 - 而不是简单地死亡/取消 - 首先检查脚本的内存消耗。

我不会详细介绍如何衡量内存消耗,因为这是一个无关的问题,可能已在SO上全面回答,但您可以使用size() as described in the Perlmonks snippet Find memory usage of perl program Proc::ProcessTable方法}。

答案 2 :(得分:1)

请注意,如果由于表锁而导致查询被卡住,则无法使用相同的连接处理程序终止查询。您必须打开与同一用户的另一个连接,并将该线程ID。

当然,您必须在哈希中存储当前打开的线程ID列表。

请注意,一旦你终止了一个线程id,其余的Perl代码就会在一个未经处理的处理程序上执行..