我正在尝试对一些有两个用途的遗留代码进行排序。它使用DBI 创建数据库,然后使用DBI connect 到该数据库。不幸的是,它为每个使用相同的代码。这意味着如果您创建sales
数据库,稍后在使用重新连接时,您必须显式调用$dbh->do('use sales')
。这会导致各种各样的问题,例如开发人员忘记这样做或数据库处理重新连接并忘记它所在的数据库。
我们尝试做的第一遍修复是让DBI::connect()
方法使用HandleError
重新连接到MySQL,如果数据库不存在,从而允许我们创建数据库。由于各种遗留原因(是的,我们都在那里),尝试在“{1}}方法之外捕获”未知数据库“错误要困难得多。
因此,我解决这个问题的第一步如下:
connect()
这是有效的,它目前对最终用户是透明的,但它也像一堆热气腾腾的零点。有没有更好的方法在连接失败时重新连接到不同的数据库?
答案 0 :(得分:7)
我不确定这是否有用,但最好使用PadWalker
:
use strict;use warnings;
use DBI;
my %attr = (RaiseError => 1, PrintError => 0);
my $dbh = DBI->connect(
$dsn,
$user,
$pass,
{
%attr,
HandleError => sub {
reconnect_if_unknown_database(
$dsn, $user, $pass, \%attr, @_
)
},
},
);
sub reconnect_if_unknown_database {
my ($dsn, $user, $pass, $attr, $msg, $drh, $dbh) = @_;
return unless $msg =~ /Unknown database/;
return unless $dsn =~ s/^[^;]+;/DBI:mysql:mysql;/;
$_[-1] = DBI->connect($dsn, $user, $pass, $attr);
}