MediaWiki
REL1_22
|
00001 <?php 00025 require_once __DIR__ . '/Maintenance.php'; 00026 00027 class InitEditCount extends Maintenance { 00028 public function __construct() { 00029 parent::__construct(); 00030 $this->addOption( 'quick', 'Force the update to be done in a single query' ); 00031 $this->addOption( 'background', 'Force replication-friendly mode; may be inefficient but 00032 avoids locking tables or lagging slaves with large updates; 00033 calculates counts on a slave if possible. 00034 00035 Background mode will be automatically used if the server is MySQL 4.0 00036 (which does not support subqueries) or if multiple servers are listed 00037 in the load balancer, usually indicating a replication environment.' ); 00038 $this->mDescription = "Batch-recalculate user_editcount fields from the revision table"; 00039 } 00040 00041 public function execute() { 00042 $dbw = wfGetDB( DB_MASTER ); 00043 $user = $dbw->tableName( 'user' ); 00044 $revision = $dbw->tableName( 'revision' ); 00045 00046 $dbver = $dbw->getServerVersion(); 00047 00048 // Autodetect mode... 00049 $backgroundMode = wfGetLB()->getServerCount() > 1 || 00050 ( $dbw instanceof DatabaseMysql && version_compare( $dbver, '4.1' ) < 0 ); 00051 00052 if ( $this->hasOption( 'background' ) ) { 00053 $backgroundMode = true; 00054 } elseif ( $this->hasOption( 'quick' ) ) { 00055 $backgroundMode = false; 00056 } 00057 00058 if ( $backgroundMode ) { 00059 $this->output( "Using replication-friendly background mode...\n" ); 00060 00061 $dbr = wfGetDB( DB_SLAVE ); 00062 $chunkSize = 100; 00063 $lastUser = $dbr->selectField( 'user', 'MAX(user_id)', '', __METHOD__ ); 00064 00065 $start = microtime( true ); 00066 $migrated = 0; 00067 for ( $min = 0; $min <= $lastUser; $min += $chunkSize ) { 00068 $max = $min + $chunkSize; 00069 $result = $dbr->query( 00070 "SELECT 00071 user_id, 00072 COUNT(rev_user) AS user_editcount 00073 FROM $user 00074 LEFT OUTER JOIN $revision ON user_id=rev_user 00075 WHERE user_id > $min AND user_id <= $max 00076 GROUP BY user_id", 00077 __METHOD__ ); 00078 00079 foreach ( $result as $row ) { 00080 $dbw->update( 'user', 00081 array( 'user_editcount' => $row->user_editcount ), 00082 array( 'user_id' => $row->user_id ), 00083 __METHOD__ ); 00084 ++$migrated; 00085 } 00086 00087 $delta = microtime( true ) - $start; 00088 $rate = ( $delta == 0.0 ) ? 0.0 : $migrated / $delta; 00089 $this->output( sprintf( "%s %d (%0.1f%%) done in %0.1f secs (%0.3f accounts/sec).\n", 00090 wfWikiID(), 00091 $migrated, 00092 min( $max, $lastUser ) / $lastUser * 100.0, 00093 $delta, 00094 $rate ) ); 00095 00096 wfWaitForSlaves(); 00097 } 00098 } else { 00099 // Subselect should work on modern MySQLs etc 00100 $this->output( "Using single-query mode...\n" ); 00101 $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)"; 00102 $dbw->query( $sql ); 00103 } 00104 00105 $this->output( "Done!\n" ); 00106 } 00107 } 00108 00109 $maintClass = "InitEditCount"; 00110 require_once RUN_MAINTENANCE_IF_MAIN;