DBI重新连接后如何挂钩

时间:2017-02-21 10:46:27

标签: perl database-connection hook dbi

我处理的是一个提供DBI抽象的模块,它自动重新连接。我需要在`DBI-> connect。

之后执行一些操作

有没有办法在不修改此模块的情况下添加钩子?我在文档中找不到运气。我错过了什么?

1 个答案:

答案 0 :(得分:3)

DBI文档有a chapter about subclassing,其中提到了$dbh->connected方法,它什么都不做。这似乎正是你想要的。

  

当使用子类化时,在成功进行新连接后,DBI-> connect方法会自动调用:

$dbh->connected($dsn, $user, $pass, \%attr);

我还没有尝试过,但它可能只需将这个连接的方法直接修补到DBI中而不需要子类化任何东西。 In connect there is definitely a call to connected

但是我不知道在哪里修补它。可能是驱动程序。快速grep of the cpan表明DBI dist中只包含两个驱动程序包括此内容。 DBD::GoferDBD::Proxy,但那个是空的。它们都在DBD::<drivername>::db包中。

假设您正在使用MySQL,那么您可以将其挂钩到您的驱动程序中。通过继承和使用该驱动程序,或者简单地将其修补。

*DBD::mysql::db::connected = sub {
    my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_;

    warn 'Connected!';
}

这应该与其他驱动程序一样,除非它们有自己的connected。在这种情况下,您应该手动将其包装起来或使用类似Class::Method::Modifiersaround之类的内容来包装它,以确保原始行为保持不变。

此时您还有实际连接的$dbh,因此如果您愿意,可以在connected的数据库中搜索。

当然,这会在每次连接之后给你回调。如果你只想获得重新连接,你可以在词法变量上创建一个闭包来计算连接并跳过第一个连接。

{
    my $connection_counter;
    *DBD::mysql::db::connected = sub {
        my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_;

        return unless $connection_counter++; # skip first connection
        warn 'Connected!';
    }
}

请注意,我没有对此进行任何测试。