summaryrefslogtreecommitdiff
path: root/maintenance/fixSlaveDesync.php
diff options
context:
space:
mode:
Diffstat (limited to 'maintenance/fixSlaveDesync.php')
-rw-r--r--maintenance/fixSlaveDesync.php133
1 files changed, 114 insertions, 19 deletions
diff --git a/maintenance/fixSlaveDesync.php b/maintenance/fixSlaveDesync.php
index e97f96c9..d2dffe54 100644
--- a/maintenance/fixSlaveDesync.php
+++ b/maintenance/fixSlaveDesync.php
@@ -22,12 +22,50 @@ if ( isset( $args[0] ) ) {
} else {
$dbw =& wfGetDB( DB_MASTER );
$maxPage = $dbw->selectField( 'page', 'MAX(page_id)', false, 'fixDesync.php' );
+ $corrupt = findPageLatestCorruption();
+ foreach ( $corrupt as $id => $dummy ) {
+ desyncFixPage( $id );
+ }
+ /*
for ( $i=1; $i <= $maxPage; $i++ ) {
desyncFixPage( $i );
if ( !($i % $reportingInterval) ) {
print "$i\n";
}
+ }*/
+}
+
+function findPageLatestCorruption() {
+ $desync = array();
+ $n = 0;
+ $dbw =& wfGetDB( DB_MASTER );
+ $masterIDs = array();
+ $res = $dbw->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
+ print "Number of pages: " . $dbw->numRows( $res ) . "\n";
+ while ( $row = $dbw->fetchObject( $res ) ) {
+ $masterIDs[$row->page_id] = $row->page_latest;
+ if ( !( ++$n % 10000 ) ) {
+ print "$n\r";
+ }
}
+ print "\n";
+ $dbw->freeResult( $res );
+
+ global $slaveIndexes;
+ foreach ( $slaveIndexes as $i ) {
+ $slaveIDs = array();
+ $db =& wfGetDB( $i );
+ $res = $db->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
+ while ( $row = $db->fetchObject( $res ) ) {
+ if ( isset( $masterIDs[$row->page_id] ) && $masterIDs[$row->page_id] != $row->page_latest ) {
+ $desync[$row->page_id] = true;
+ print $row->page_id . "\t";
+ }
+ }
+ $db->freeResult( $res );
+ }
+ print "\n";
+ return $desync;
}
function desyncFixPage( $pageID ) {
@@ -36,10 +74,20 @@ function desyncFixPage( $pageID ) {
# Check for a corrupted page_latest
$dbw =& wfGetDB( DB_MASTER );
- $realLatest = $dbw->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ), $fname );
+ $dbw->begin();
+ $realLatest = $dbw->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ),
+ $fname, 'FOR UPDATE' );
+ #list( $masterFile, $masterPos ) = $dbw->getMasterPos();
$found = false;
foreach ( $slaveIndexes as $i ) {
$db =& wfGetDB( $i );
+ /*
+ if ( !$db->masterPosWait( $masterFile, $masterPos, 10 ) ) {
+ echo "Slave is too lagged, aborting\n";
+ $dbw->commit();
+ sleep(10);
+ return;
+ }*/
$latest = $db->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ), $fname );
$max = $db->selectField( 'revision', 'MAX(rev_id)', false, $fname );
if ( $latest != $realLatest && $realLatest < $max ) {
@@ -49,11 +97,14 @@ function desyncFixPage( $pageID ) {
}
}
if ( !$found ) {
+ print "page_id $pageID seems fine\n";
+ $dbw->commit();
return;
}
- # Find the missing revision
- $res = $dbw->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ), $fname );
+ # Find the missing revisions
+ $res = $dbw->select( 'revision', array( 'rev_id' ), array( 'rev_page' => $pageID ),
+ $fname, 'FOR UPDATE' );
$masterIDs = array();
while ( $row = $dbw->fetchObject( $res ) ) {
$masterIDs[] = $row->rev_id;
@@ -66,35 +117,79 @@ function desyncFixPage( $pageID ) {
$slaveIDs[] = $row->rev_id;
}
$db->freeResult( $res );
- $missingIDs = array_diff( $masterIDs, $slaveIDs );
+ if ( count( $masterIDs ) < count( $slaveIDs ) ) {
+ $missingIDs = array_diff( $slaveIDs, $masterIDs );
+ if ( count( $missingIDs ) ) {
+ print "Found " . count( $missingIDs ) . " lost in master, copying from slave... ";
+ $dbFrom = $db;
+ $dbTo = $dbw;
+ $found = true;
+ $toMaster = true;
+ } else {
+ $found = false;
+ }
+ } else {
+ $missingIDs = array_diff( $masterIDs, $slaveIDs );
+ if ( count( $missingIDs ) ) {
+ print "Found " . count( $missingIDs ) . " missing revision(s), copying from master... ";
+ $dbFrom = $dbw;
+ $dbTo = $db;
+ $found = true;
+ $toMaster = false;
+ } else {
+ $found = false;
+ }
+ }
- if ( count( $missingIDs ) ) {
- print "Found " . count( $missingIDs ) . " missing revision(s), copying from master... ";
+ if ( $found ) {
foreach ( $missingIDs as $rid ) {
print "$rid ";
# Revision
- $row = $dbw->selectRow( 'revision', '*', array( 'rev_id' => $rid ), $fname );
- foreach ( $slaveIndexes as $i ) {
- $db =& wfGetDB( $i );
- $db->insert( 'revision', get_object_vars( $row ), $fname, 'IGNORE' );
+ $row = $dbFrom->selectRow( 'revision', '*', array( 'rev_id' => $rid ), $fname );
+ if ( $toMaster ) {
+ $id = $dbw->selectField( 'revision', 'rev_id', array( 'rev_id' => $rid ),
+ $fname, 'FOR UPDATE' );
+ if ( $id ) {
+ echo "Revision already exists\n";
+ $found = false;
+ break;
+ } else {
+ $dbw->insert( 'revision', get_object_vars( $row ), $fname, 'IGNORE' );
+ }
+ } else {
+ foreach ( $slaveIndexes as $i ) {
+ $db =& wfGetDB( $i );
+ $db->insert( 'revision', get_object_vars( $row ), $fname, 'IGNORE' );
+ }
}
# Text
- $row = $dbw->selectRow( 'text', '*', array( 'old_id' => $row->rev_text_id ), $fname );
- foreach ( $slaveIndexes as $i ) {
- $db =& wfGetDB( $i );
- $db->insert( 'text', get_object_vars( $row ), $fname, 'IGNORE' );
+ $row = $dbFrom->selectRow( 'text', '*', array( 'old_id' => $row->rev_text_id ), $fname );
+ if ( $toMaster ) {
+ $dbw->insert( 'text', get_object_vars( $row ), $fname, 'IGNORE' );
+ } else {
+ foreach ( $slaveIndexes as $i ) {
+ $db =& wfGetDB( $i );
+ $db->insert( 'text', get_object_vars( $row ), $fname, 'IGNORE' );
+ }
}
}
print "done\n";
}
- print "Fixing page_latest... ";
- foreach ( $slaveIndexes as $i ) {
- $db =& wfGetDB( $i );
- $db->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), $fname );
+ if ( $found ) {
+ print "Fixing page_latest... ";
+ if ( $toMaster ) {
+ #$dbw->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), $fname );
+ } else {
+ foreach ( $slaveIndexes as $i ) {
+ $db =& wfGetDB( $i );
+ $db->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), $fname );
+ }
+ }
+ print "done\n";
}
- print "done\n";
+ $dbw->commit();
}
?>