Made updateSpecialPages.php more robust to database problems
This commit is contained in:
parent
faabce5662
commit
6c1ccfd02e
4 changed files with 122 additions and 62 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue