Made updateSpecialPages.php more robust to database problems

This commit is contained in:
Tim Starling 2005-04-24 08:31:12 +00:00
parent faabce5662
commit 6c1ccfd02e
4 changed files with 122 additions and 62 deletions

View file

@ -44,6 +44,7 @@ class Database {
var $mTablePrefix;
var $mFlags;
var $mTrxLevel = 0;
var $mErrorCount = 0;
/**#@-*/
#------------------------------------------------------------------------------
@ -105,6 +106,13 @@ class Database {
return wfSetVar( $this->mTrxLevel, $level );
}
/**
* Number of errors logged, only useful when errors are ignored
*/
function errorCount( $count = NULL ) {
return wfSetVar( $this->mErrorCount, $count );
}
/**#@+
* Get function
*/
@ -308,7 +316,7 @@ class Database {
$ret = $this->doQuery( $commentedSql );
# Try reconnecting if the connection was lost
if ( false === $ret && $this->lastErrno() == 2013 ) {
if ( false === $ret && ( $this->lastErrno() == 2013 || $this->lastErrno() == 2006 ) ) {
# Transaction is gone, like it or not
$this->mTrxLevel = 0;
wfDebug( "Connection lost, reconnecting...\n" );
@ -321,7 +329,6 @@ class Database {
}
if ( false === $ret ) {
# Automatic reconnect
$this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
}
@ -355,6 +362,7 @@ class Database {
global $wgCommandLineMode, $wgFullyInitialised;
# Ignore errors during error handling to avoid infinite recursion
$ignore = $this->ignoreErrors( true );
$this->mErrorCount ++;
if( $ignore || $tempIgnore ) {
wfDebug("SQL ERROR (ignored): " . $error . "\n");

View file

@ -447,4 +447,18 @@ class LoadBalancer {
function getLaggedSlaveMode() {
return $this->mLaggedSlaveMode;
}
function pingAll() {
$success = true;
foreach ( $this->mConnections as $i => $conn ) {
if ( $this->isOpen( $i ) ) {
if ( !$this->mConnections[$i]->ping() ) {
$success = false;
}
}
}
return $success;
}
}
?>

View file

@ -127,6 +127,72 @@ class QueryPage {
return false;
}
/**
* Clear the cache and save new results
*/
function recache( $ignoreErrors = true ) {
$fname = get_class($this) . '::recache';
$dbw =& wfGetDB( DB_MASTER );
$dbr =& wfGetDB( DB_SLAVE, array( $this->getName(), 'QueryPage::recache', 'vslow' ) );
if ( !$dbw || !$dbr ) {
return false;
}
$querycache = $dbr->tableName( 'querycache' );
if ( $ignoreErrors ) {
$ignoreW = $dbw->ignoreErrors( true );
$ignoreR = $dbr->ignoreErrors( true );
}
# Clear out any old cached data
$dbw->delete( 'querycache', array( 'qc_type' => $this->getName() ), $fname );
# Do query
$res = $dbr->query( $this->getSQL() . $this->getOrder() . $dbr->limitResult( 1000,0 ), $fname );
$num = false;
if ( $res ) {
$num = $dbr->numRows( $res );
# Fetch results
$insertSql = "INSERT INTO $querycache (qc_type,qc_namespace,qc_title,qc_value) VALUES ";
$first = true;
while ( $res && $row = $dbr->fetchObject( $res ) ) {
if ( $first ) {
$first = false;
} else {
$insertSql .= ',';
}
if ( isset( $row->value ) ) {
$value = $row->value;
} else {
$value = '';
}
$insertSql .= '(' .
$dbw->addQuotes( $row->type ) . ',' .
$dbw->addQuotes( $row->namespace ) . ',' .
$dbw->addQuotes( $row->title ) . ',' .
$dbw->addQuotes( $value ) . ')';
}
# Save results into the querycache table on the master
if ( !$first ) {
if ( !$dbw->query( $insertSql, $fname ) ) {
// Set result to false to indicate error
$dbr->freeResult( $res );
$res = false;
}
}
if ( $res ) {
$dbr->freeResult( $res );
}
if ( $ignoreErrors ) {
$dbw->ignoreErrors( $ignoreW );
$dbr->ignoreErrors( $ignoreR );
}
}
return $num;
}
/**
* This is the actual workhorse. It does everything needed to make a
* real, honest-to-gosh query page.
@ -134,7 +200,7 @@ class QueryPage {
* @param $offset database query offset
* @param $limit database query limit
*/
function doQuery( $offset, $limit, $recache = false ) {
function doQuery( $offset, $limit ) {
global $wgUser, $wgOut, $wgLang, $wgRequest, $wgContLang;
global $wgMiserMode;
@ -150,54 +216,7 @@ class QueryPage {
if ( $this->isExpensive() ) {
// Disabled recache parameter due to retry problems -- TS
// $recache = $wgRequest->getBool( 'recache' );
if( $recache ) {
# Clear out any old cached data
$dbw->delete( 'querycache', array( 'qc_type' => $sname ), $fname );
# Do query on the (possibly out of date) slave server
$slowDB =& wfGetDB( DB_SLAVE, array( $this->getName(), 'QueryPage-recache', 'vslow' ) );
$maxstored = 1000;
$res = $slowDB->query( $sql . $this->getOrder() . $dbr->limitResult( $maxstored,0 ), $fname );
# Fetch results
$insertSql = "INSERT INTO $querycache (qc_type,qc_namespace,qc_title,qc_value) VALUES ";
$first = true;
while ( $row = $dbr->fetchObject( $res ) ) {
if ( $first ) {
$first = false;
} else {
$insertSql .= ',';
}
if ( isset( $row->value ) ) {
$value = $row->value;
} else {
$value = '';
}
$insertSql .= '(' .
$dbw->addQuotes( $row->type ) . ',' .
$dbw->addQuotes( $row->namespace ) . ',' .
$dbw->addQuotes( $row->title ) . ',' .
$dbw->addQuotes( $value ) . ')';
}
# Save results into the querycache table on the master
if ( !$first ) {
$dbw->query( $insertSql, $fname );
}
# Set result pointer to allow reading for display
$numRows = $dbr->numRows( $res );
if ( $numRows <= $offset ) {
$num = 0;
} else {
$dbr->dataSeek( $res, $offset );
$num = max( $limit, $numRows - $offset );
}
}
if( $wgMiserMode || $recache ) {
if( $wgMiserMode ) {
$type = $dbr->strencode( $sname );
$sql =
"SELECT qc_type as type, qc_namespace as namespace,qc_title as title, qc_value as value

View file

@ -8,6 +8,7 @@ require_once( 'SpecialPage.php' );
require_once( 'QueryPage.php' );
$wgOut->disable();
$dbw =& wfGetDB( DB_MASTER );
foreach ( $wgQueryPages as $page ) {
list( $class, $special ) = $page;
@ -27,22 +28,40 @@ foreach ( $wgQueryPages as $page ) {
if ( $queryPage->isExpensive() ) {
$t1 = explode( ' ', microtime() );
$num = $queryPage->doQuery( 0, 0, true );
# Do the query
$num = $queryPage->recache();
$t2 = explode( ' ', microtime() );
print "got $num rows in ";
if ( $num === false ) {
print "FAILED: database error\n";
} else {
print "got $num rows in ";
$elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
$hours = intval( $elapsed / 3600 );
$minutes = intval( $elapsed % 3600 / 60 );
$seconds = $elapsed - $hours * 3600 - $minutes * 60;
if ( $hours ) {
print $hours . 'h ';
$elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
$hours = intval( $elapsed / 3600 );
$minutes = intval( $elapsed % 3600 / 60 );
$seconds = $elapsed - $hours * 3600 - $minutes * 60;
if ( $hours ) {
print $hours . 'h ';
}
if ( $minutes ) {
print $minutes . 'm ';
}
printf( "%.2fs\n", $seconds );
}
if ( $minutes ) {
print $minutes . 'm ';
# Reopen any connections that have closed
if ( !$wgLoadBalancer->pingAll()) {
print "\n";
do {
print "Connection failed, reconnecting in 10 seconds...\n";
sleep(10);
} while ( !$wgLoadBalancer->pingAll() );
print "Reconnected\n\n";
} else {
# Commit the results
$dbw->immediateCommit();
}
printf( "%.2f s\n", $seconds );
} else {
print "cheap, skipped\n";
}