various improvements
authorTim Starling <tstarling@users.mediawiki.org>
Thu, 28 Sep 2006 09:05:28 +0000 (09:05 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Thu, 28 Sep 2006 09:05:28 +0000 (09:05 +0000)
maintenance/fixSlaveDesync.php

index e97f96c..d2dffe5 100644 (file)
@@ -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();
 }
 
 ?>