X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=maintenance%2FpopulateArchiveRevId.php;h=60f5e8a12611cf07de699fa080597d902aa13857;hb=039d957b43dda31439d43d34db5aa7175798dbbf;hp=e493506237b8c0d2203fd97a6ddcbe4a75e8f574;hpb=c8c2d83312229284c552ad19baeacc588c63145d;p=lhc%2Fweb%2Fwiklou.git diff --git a/maintenance/populateArchiveRevId.php b/maintenance/populateArchiveRevId.php index e493506237..60f5e8a126 100644 --- a/maintenance/populateArchiveRevId.php +++ b/maintenance/populateArchiveRevId.php @@ -21,6 +21,7 @@ * @ingroup Maintenance */ +use Wikimedia\Rdbms\DBQueryError; use Wikimedia\Rdbms\IDatabase; require_once __DIR__ . '/Maintenance.php'; @@ -49,6 +50,7 @@ class PopulateArchiveRevId extends LoggedUpdateMaintenance { protected function doDBUpdates() { $this->output( "Populating ar_rev_id...\n" ); $dbw = $this->getDB( DB_MASTER ); + self::checkMysqlAutoIncrementBug( $dbw ); // Quick exit if there are no rows needing updates. $any = $dbw->selectField( @@ -86,6 +88,53 @@ class PopulateArchiveRevId extends LoggedUpdateMaintenance { } } + /** + * Check for (and work around) a MySQL auto-increment bug + * + * (T202032) MySQL until 8.0 and MariaDB until some version after 10.1.34 + * don't save the auto-increment value to disk, so on server restart it + * might reuse IDs from deleted revisions. We can fix that with an insert + * with an explicit rev_id value, if necessary. + * + * @param IDatabase $dbw + */ + public static function checkMysqlAutoIncrementBug( IDatabase $dbw ) { + if ( $dbw->getType() !== 'mysql' ) { + return; + } + + if ( !self::$dummyRev ) { + self::$dummyRev = self::makeDummyRevisionRow( $dbw ); + } + + $ok = false; + while ( !$ok ) { + try { + $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) { + $dbw->insert( 'revision', self::$dummyRev, $fname ); + $id = $dbw->insertId(); + $toDelete[] = $id; + + $maxId = max( + (int)$dbw->selectField( 'archive', 'MAX(ar_rev_id)', [], __METHOD__ ), + (int)$dbw->selectField( 'slots', 'MAX(slot_revision_id)', [], __METHOD__ ) + ); + if ( $id <= $maxId ) { + $dbw->insert( 'revision', [ 'rev_id' => $maxId + 1 ] + self::$dummyRev, $fname ); + $toDelete[] = $maxId + 1; + } + + $dbw->delete( 'revision', [ 'rev_id' => $toDelete ], $fname ); + } ); + $ok = true; + } catch ( DBQueryError $e ) { + if ( $e->errno != 1062 ) { // 1062 is "duplicate entry", ignore it and retry + throw $e; + } + } + } + } + /** * Assign new ar_rev_ids to a set of ar_ids. * @param IDatabase $dbw