我正在使用Apache2.2(worker)/ mod_perl 2.0.4 / Apache :: DBI / CGI :: Session和Firebird RDBMS .
我还编写了CGI :: Session :: Driver :: firebird.pm来使用Firebird RDBMS . 数据库连接由Apache :: DBI汇集,并提供CGI :: Session {Handle => $ dbh}的连接句柄 .
DB连接数等于工作进程数 .
我在3个月前发布了Programming with Apache::DBI and firebird. Get Stucked httpd on exception . 我找到了这个问题的原因,并想知道如何解决它 .
$dbh = DBI->connect("dbi:Firebird:db=$DBSERVER:/home/cdbs/xxnet.fdb;
ib_charset=UTF8;ib_dialect=3",$DBUSER,$DBPASS,{
AutoCommit=>1,
LongReadLen=>8192,
RaiseError=>1
});
my $session = new CGI::Session('dbi:firebird',$sessid,{Handle=>$dbh});
my $ses_p1 = $session->param('p1');
eval { $dbh->begin_work()
my $sql = "SELECT * FROM SAMPLETABLE"
my $st = $dbh->prepare($sql);
$st->execute();
while (my $R = $st->fetchrow_hashref()) {
...
}
$st->finish();
}; warn $@ if $@;
if ($@) {
$dbh->rollback();
}else{
$dbh->commit();
}
$session->flush();
发生sql错误时,eval块会捕获异常和回滚事务 . 之后,CGI :: Session不再检索会话对象 .
因为prepare_cached语句在CGI :: Session :: DBI.pm处失败 . CGI :: Session :: DBI.pm使用prepare_cached($ sql,undef,3) . '3'是使用缓存语句的最安全的方法,但在这种情况下它永远不会找到破坏的语句 .
如何解决这个问题?提出更改CGI :: Session :: DBI.pm的请求以使用prepare()语句?在firebird.pm中写store(),retrieve(),traverse()函数来使用prepare()语句?
捕获异常后,其他prepare_cached()可能会失败...
1)我在CGI :: Session-> errstr()上添加了die语句我收到错误“new():failed:load():无法检索数据:retrieve():$ sth-> execute failed with error message “2)如果$ session有效,我会在session-> load()之后刷新会话对象,更改存储到DB . 3)我将begin_work()替换为 = 0结果相同 . 我可以在捕获异常和回滚后正常使用$ dbh,但是新的CGI :: Session返回错误 . ------------------------------------------已添加2017/07/26 18: 47 JST
请给我你的建议 .
谢谢 .
1 回答
在请求更改为CGI :: Session :: Driver :: DBI.pm之前,您可以尝试各种各样的事情......
首先,更改调用
new CGI::Session
的方式,以便在创建或加载会话时诊断问题是否发生:方法
param
或delete
将更改存储在$session
句柄内的会话中,而不是存储在DB中 .flush
在DB中存储会话句柄内的更改 . 仅在session-> param set / update或会话删除后使用$session->flush()
:方法
flush
不会破坏$session
句柄(您仍然可以在刷新后调用$session->param('p1')
) . 在某些情况下,mod_perl缓存$session
会导致下一次加载同一会话的尝试出现问题 . 在这些情况下,它需要在不再需要时销毁:我可以建议的最后一件事是避免使用
begin_work
方法,而是使用AutoCommit
来控制事务行为(因为DBD::Firebird documentation表示应该控制事务的方式)和commit
在eval块中:你说你为Firebird编写了自己的会话驱动程序......你应该看看CGI / Driver / sqlite.pm或CGI / Driver / mysql.pm是如何制作的,也许你需要写一些你想念的提取方法......
希望这可以帮助!!