Fix bug in BacklinkCache: the lack of an ORDER BY clause in getLinks(), combined with the lack of sensible indexes on the categorylinks table, was causing partition() to return starts and ends scaterred randomly across the result set. For large jobs, many partitions end up being large, causing HTMLCacheUpdate::doPartialUpdate() to repartition, thus requeueing jobs in an infinite recursive loop.

The BacklinkCache bug was there since r47317, but was relatively harmless until r54841 introduced the infinite loop issue.
This commit is contained in:
Tim Starling 2009-12-04 01:55:05 +00:00
parent cee6cff6f6
commit 1eae9941d9
2 changed files with 17 additions and 3 deletions

View file

@ -661,6 +661,8 @@ Hopefully we will remove this configuration var soon)
* (bug 18762) both redirects and links get fixed one after another if
redirects-only switch is not present
* (bug 20159) thumbnails rerendered if older that $wgThumbnailEpoch
* Fixed a bug which in some situations causes the job queue to grow forever,
due to an infinite loop of job requeues.
== API changes in 1.16 ==

View file

@ -53,13 +53,13 @@ class BacklinkCache {
public function getLinks( $table, $startId = false, $endId = false ) {
wfProfileIn( __METHOD__ );
$fromField = $this->getPrefix( $table ) . '_from';
if ( $startId || $endId ) {
// Partial range, not cached
wfDebug( __METHOD__.": from DB (uncacheable range)\n" );
$conds = $this->getConditions( $table );
// Use the from field in the condition rather than the joined page_id,
// because databases are stupid and don't necessarily propagate indexes.
$fromField = $this->getPrefix( $table ) . '_from';
if ( $startId ) {
$conds[] = "$fromField >= " . intval( $startId );
}
@ -71,7 +71,10 @@ class BacklinkCache {
array( 'page_namespace', 'page_title', 'page_id'),
$conds,
__METHOD__,
array('STRAIGHT_JOIN') );
array(
'STRAIGHT_JOIN',
'ORDER BY' => $fromField
) );
$ta = TitleArray::newFromResult( $res );
wfProfileOut( __METHOD__ );
return $ta;
@ -84,7 +87,10 @@ class BacklinkCache {
array( 'page_namespace', 'page_title', 'page_id' ),
$this->getConditions( $table ),
__METHOD__,
array('STRAIGHT_JOIN') );
array(
'STRAIGHT_JOIN',
'ORDER BY' => $fromField,
) );
$this->fullResultCache[$table] = $res;
}
$ta = TitleArray::newFromResult( $this->fullResultCache[$table] );
@ -225,6 +231,12 @@ class BacklinkCache {
$row = $res->fetchObject();
$end = $row->page_id - 1;
}
# Sanity check order
if ( $start && $end && $start > $end ) {
throw new MWException( __METHOD__.': Internal error: query result out of order' );
}
$batches[] = array( $start, $end );
}
return array( 'numRows' => $numRows, 'batches' => $batches );