I'm getting this on four different web sites on three different
machines and it's causing major problems. Even if you don't have any
suggestions on the problem, if you have any comments on the
architecture I'd appreciate them.
The symptom.
Apparently randomly a page will come up with no data from the
database. DBIx::Recordset believes there is data--if there's a
->Next() loop it will even loop the correct number of times--but the
actual data from the hash is empty. The probably typically goes away
after a few reloads--but that may just mean I've gotten a different
Apache process.
The configuration.
Various Linux boxes.
Perl 5.6.0 through 5.6.1
Embperl 1.3.3 and 1.3.4
DBIx::Recordset, most recent version.
MySQL.
I use the $ref variation on the return values rather than * as it's
easier to pass around.
The architecture.
I believe I've seen this under straight HTML::Embperl, but all my
sites are currently running HTML::EmbperlObject.
1. Apache::DBI loaded in startup.pl (not that not loading it changes anything).
2. All site templates have a line like this:
[- Execute({ isa => 'SiteInit.html' }); -]
3. SiteInit.html defines (in a [! !]) a routine which checks to see
if $sitename::Commons exists, if not, it creates the object. If so,
it returns it. This lets me have a generic call to $_[0]->Commons()
to get my base object structure without having to worry about which
site I'm in. So I get reusable code, but separate objects for each
site, even in a virtual hosting situation. Out of paranoia I've put
in some other checks as well:
sub Commons {
my ($db, $dbh);
my ($database, $user, $pass) = ('xxx', 'xxx', 'xxx');
if (!$PureM::Commons) {
#print LOG "CACHE_ERROR: Creating PureM::Commons ($$)\n";
$PureM::Commons = new SWC::Commons(database => $database,
username => $user,
password => $pass,
basepath => $ENV{DOCUMENT_ROOT});
} elsif ($db = $PureM::Commons->{_db}) {
if (!($dbh = $db->DBHdl())) {
print LOG "CACHE_ERROR: PureM::Commons DBD not
defined: $db ($$)\n";
$PureM::Commons = new SWC::Commons(database => $database,
username => $user,
password => $pass,
basepath =>
$ENV{DOCUMENT_ROOT});
} elsif (!$dbh->{Active}) {
print LOG "CACHE_ERROR: PureM::Commons DBD not
active: $dbh ($$)\n";
$PureM::Commons = new SWC::Commons(database => $database,
username => $user,
password => $pass,
basepath =>
$ENV{DOCUMENT_ROOT});
} else {
#print LOG "CACHE_ERROR: Already have PureM::Commons ($$)\n";
}
}
return $PureM::Commons;
}
I don't think I'm getting cache errors, unfortunately on the live
sites I have logging turned off, I'll have to change this to dump to
the apache log file to see if there is anything there.
4. Every database call in the library calls a setupDB method, passing
it the table and table attributes for the database operation it's
going to do. setupDB looks like this:
if (!$this->{_db}) {
$DBIx::Recordset::FetchsizeWarn = 0;
$this->{_db} = new DBIx::Database({
'!DataSource' => $connect,
'!DBIAttr' => {PrintError => 0, RaiseError => 1,
AutoCommit => 1},
'!Username' => $this->{username},
'!Password' => $this->{password},
'!KeepOpen' => 1,
'!SaveAs' => 'Commons',
}) || die $DBI::errstr;
*** Sudden thought ***. I'm not using the SaveAs, and it's the same
across sites, so using it would get me in trouble. Is it doing any
harm?
...
$this->{_setup} = {
'!DataSource' => $this->{_db},
'!LongNames' => 2,
'!Serial' => 'id',
'!Filter' =>
{
'dtm' => $dateparse,
'dtc' => $dateparse,
'dtv' => $dateparse,
'verifydate' => $dateparse,
'validdate' => $dateparse,
'approveddate' => $dateparse,
'pubdate' => $dateparse,
},
};
}
my %setup = %{$this->{_setup}};
my ($key, $val);
while (($key, $val) = each(%args)) {
$setup{$key} = $val;
}
$set = DBIx::Recordset->Setup(\%setup);
return $set;
So a typical call looks like this:
$set = $this->setupDB(
'!Table' => 'keywordmap,keyword',
'!TabJoin' => 'keyword JOIN keywordmap',
'!TabRelation' => 'id = keyword_id',
);
$$set->Search($args);
return $set;
This model keeps the higher level caller from setting database stuff
we don't want them to set (e.g. through cgi arguments). We can set
the ! arguments in the setupDB call, then they are restricted to the
$ arguments.
Does this all seem like a reasonable way to preserve database
connections in a virtual host environment?
Does *anyone* have any idea why occasionally the data doesn't show up?
--
Kee Hinckley - Somewhere.Com, LLC
http://consulting.somewhere.com/
I'm not sure which upsets me more: that people are so unwilling to accept
responsibility for their own actions, or that they are so eager to regulate
everyone else's.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]