X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=maintenance%2FinitEditCount.php;h=b7301643adf172a4304b25f63507ed46bdc81496;hb=17484e507dd9b9c6c4d182cea940980dabc7f787;hp=a975f356162d7c6bc7562924f71cc0dbfeddf39e;hpb=288a7eb7f18ebc1f98f6ad65ede01c9ea39d9e9b;p=lhc%2Fweb%2Fwiklou.git diff --git a/maintenance/initEditCount.php b/maintenance/initEditCount.php index a975f35616..b7301643ad 100644 --- a/maintenance/initEditCount.php +++ b/maintenance/initEditCount.php @@ -1,40 +1,108 @@ addOption( 'quick', 'Force the update to be done in a single query' ); + $this->addOption( 'background', 'Force replication-friendly mode; may be inefficient but + avoids locking tables or lagging slaves with large updates; + calculates counts on a slave if possible. -$dbw = wfGetDB( DB_MASTER ); -$user = $dbw->tableName( 'user' ); -$revision = $dbw->tableName( 'revision' ); +Background mode will be automatically used if the server is MySQL 4.0 +(which does not support subqueries) or if multiple servers are listed +in $wgDBservers, usually indicating a replication environment.' ); + $this->mDescription = "Batch-recalculate user_editcount fields from the revision table"; + } -$dbver = $dbw->getServerVersion(); -if( ($dbw instanceof DatabaseMySql && version_compare( $dbver, '4.1' ) < 0) - || isset( $options['force-mysql4'] ) ) { - - echo "Warning: MySQL $dbver; using hacky MySQL 4.0 compatibility query...\n"; - $sql = "CREATE TEMPORARY TABLE temp_editcount ( - temp_user_id INT, - temp_user_editcount INT - )"; - $dbw->query( $sql ); + public function execute() { + global $wgDBservers; + $dbw = wfGetDB( DB_MASTER ); + $user = $dbw->tableName( 'user' ); + $revision = $dbw->tableName( 'revision' ); + + $dbver = $dbw->getServerVersion(); + + // Autodetect mode... + $backgroundMode = count( $wgDBservers ) > 1 || + ($dbw instanceof DatabaseMySql && version_compare( $dbver, '4.1' ) < 0); - $sql = "INSERT INTO temp_editcount - (temp_user_id, temp_user_editcount) - SELECT rev_user, COUNT(rev_user) - FROM $revision GROUP BY rev_user"; - $dbw->query( $sql ); - - $sql = "UPDATE $user - LEFT OUTER JOIN temp_editcount ON user_id=temp_user_id - SET user_editcount=IF(temp_user_editcount IS NULL,0,temp_user_editcount)"; - $dbw->query( $sql ); -} else { - // Subselect should work on modern MySQLs etc - $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)"; - $dbw->query( $sql ); -} + if( $this->hasOption('background') ) { + $backgroundMode = true; + } elseif( $this->hasOption('quick') ) { + $backgroundMode = false; + } + + if( $backgroundMode ) { + $this->output( "Using replication-friendly background mode...\n" ); + + $dbr = wfGetDB( DB_SLAVE ); + $chunkSize = 100; + $lastUser = $dbr->selectField( 'user', 'MAX(user_id)', '', __METHOD__ ); -echo "Done!\n"; + $start = microtime( true ); + $migrated = 0; + for( $min = 0; $min <= $lastUser; $min += $chunkSize ) { + $max = $min + $chunkSize; + $result = $dbr->query( + "SELECT + user_id, + COUNT(rev_user) AS user_editcount + FROM $user + LEFT OUTER JOIN $revision ON user_id=rev_user + WHERE user_id > $min AND user_id <= $max + GROUP BY user_id", + __METHOD__ ); + + foreach( $result as $row ) { + $dbw->update( 'user', + array( 'user_editcount' => $row->user_editcount ), + array( 'user_id' => $row->user_id ), + __METHOD__ ); + ++$migrated; + } + $dbr->freeResult( $result ); + + $delta = microtime( true ) - $start; + $rate = ($delta == 0.0) ? 0.0 : $migrated / $delta; + $this->output( sprintf( "%s %d (%0.1f%%) done in %0.1f secs (%0.3f accounts/sec).\n", + wfWikiID(), + $migrated, + min( $max, $lastUser ) / $lastUser * 100.0, + $delta, + $rate ) ); + + wfWaitForSlaves( 10 ); + } + } else { + // Subselect should work on modern MySQLs etc + $this->output( "Using single-query mode...\n" ); + $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)"; + $dbw->query( $sql ); + } + + $this->output( "Done!\n" ); + } +} -?> +$maintClass = "InitEditCount"; +require_once( DO_MAINTENANCE );