From 6c1ccfd02edd95fa5c6ee490e3bb01e047829321 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Sun, 24 Apr 2005 08:31:12 +0000 Subject: [PATCH] Made updateSpecialPages.php more robust to database problems --- includes/Database.php | 12 ++- includes/LoadBalancer.php | 14 ++++ includes/QueryPage.php | 117 +++++++++++++++++------------ maintenance/updateSpecialPages.php | 41 +++++++--- 4 files changed, 122 insertions(+), 62 deletions(-) diff --git a/includes/Database.php b/includes/Database.php index 348f18e3bc..51104db682 100644 --- a/includes/Database.php +++ b/includes/Database.php @@ -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"); diff --git a/includes/LoadBalancer.php b/includes/LoadBalancer.php index 96ecece327..18021d5a90 100644 --- a/includes/LoadBalancer.php +++ b/includes/LoadBalancer.php @@ -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; + } } + +?> diff --git a/includes/QueryPage.php b/includes/QueryPage.php index 925083e0d0..01af31ab8c 100644 --- a/includes/QueryPage.php +++ b/includes/QueryPage.php @@ -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 diff --git a/maintenance/updateSpecialPages.php b/maintenance/updateSpecialPages.php index 61f319e4ab..97967b39ca 100644 --- a/maintenance/updateSpecialPages.php +++ b/maintenance/updateSpecialPages.php @@ -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"; } -- 2.20.1