5

在工作中,我们有一个 DBA,他说他的 RAC 工作得很好,但事实并非如此。像 Toad 或 SQL Developer 这样的 SQL IDE 会随机断开它们的连接(我怀疑是因为 RAC 的网络设置不正确)。我想通过测试来证明我的理论。我猜一个 perl 脚本可以解决问题:

步骤 1. ping 数据库的 IP

步骤 2. 如果 IP 已启动,则尝试连接到数据库

步骤 3. 如果已连接,则从双重连接中选择 sysdate 并关闭连接

步骤 4. 等待一段时间,然后重新开始

我已经设法使用 DBI 在 Perl 中编写了这个,但我不知道如何使连接和查询执行超时。是否有一些解决方案可以让这些事情超时?

4

2 回答 2

7

alarm()您可以使用与 DBI 相关的信号来使用和来实现超时$SIG{ALRM}

从cpan 和cpan pod上的DBI模块

暂停

实现超时的传统方法是设置 $SIG{ALRM} 来引用将在 ALRM 信号到达时执行的一些代码,然后调用 alarm($seconds) 来安排在 $seconds 中传递 ALRM 信号未来。

例如:

我的 $dbh = DBI->connect("DBI:SQLRelay:host=$hostname;port=$port;socket=", $user, $password) 或死 DBI->errstr;

我的 $sth = $dbh->prepare($query) 或死 $dbh->errstr;

  eval {
    local $SIG{ALRM} = sub { die "TIMEOUT\n" }; # \n is required
    eval {
         alarm($seconds);
         if(! $sth->execute() ) { # execute query
                print "Error executing query!\n"
         }
    };
    # 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

第一个(外部)评估用于避免“要执行的代码”死掉并且警报在取消之前触发的不太可能但可能的机会。如果没有外部 eval,如果发生这种情况,如果您没有 ALRM 处理程序或将调用非本地警报处理程序,您的程序将死亡。

于 2013-02-08T09:34:59.403 回答
3

它似乎取决于您连接到哪个数据库后端。例如,DBD::mysql确实记录了这样一个超时值:

mysql_connect_timeout

If your DSN contains the option "mysql_connect_timeout=##", the connect request to the server will timeout if it has not been

在给定的秒数后成功。

但是,我没有看到为 Oracle 记录的相同内容。

我确实在 DBI 文档中找到了关于使用信号处理进行此操作的讨论。

于 2013-02-07T19:54:56.463 回答