rdbms: Fix GTID style detection for MySQL servers

WHAT:
- Return the GTID style from `MySQLPrimaryPos::parseGTID`, which already identifies the style during parse.
- Rely on `parseGTID`'s detection in `MySQLPrimaryPos::init`.

WHY:
- When GTID-based replication is enabled and MySQL is used for the database, MediaWiki misidentifies the engine as MariaDB.
- This causes position waits to fail with "No active GTIDs in $1 share a domain with those in $1".
- This is a regression caused by I232274feb12c0ce4826be2c46a35315b425f6673:
  - Before that change, parseGTID returned the domain ID as an integer for MariaDB and as a string for MySQL.
  - The `init` method used this fact (`is_int`) when determining the GTID style.
  - After the change, parseGTID always returns the domain ID as a string.
  - The check in `init` was incorrectly updated to expect a string for MariaDB, but did not account for MySQL's source ID also being a string.

Change-Id: I4951e7967a45bae10d26b06ee236a55279fa8fb9
(cherry picked from commit 54154c87c084543fd659f24ae6b4c276184259cc)
This commit is contained in:
alex4401 2025-07-18 19:14:53 +02:00 committed by Alex44019
parent 8728f29a32
commit 6ecb7a4272

View file

@ -71,7 +71,7 @@ class MySQLPrimaryPos implements Stringable, DBPrimaryPos {
throw new InvalidArgumentException( "Invalid GTID '$gtid'." );
}
[ $domain, $eventNumber ] = $components;
[ $domain, $eventNumber, , $this->style ] = $components;
if ( isset( $this->gtids[$domain] ) ) {
// For MySQL, handle the case where some past issue caused a gap in the
// executed GTID set, e.g. [last_purged+1,N-1] and [N+1,N+2+K]. Ignore the
@ -83,12 +83,6 @@ class MySQLPrimaryPos implements Stringable, DBPrimaryPos {
} else {
$this->gtids[$domain] = $gtid;
}
if ( is_string( $domain ) ) {
$this->style = self::GTID_MARIA; // gtid_domain_id
} else {
$this->style = self::GTID_MYSQL; // server_uuid
}
}
if ( !$this->gtids ) {
throw new InvalidArgumentException( "GTID set cannot be empty." );
@ -260,8 +254,8 @@ class MySQLPrimaryPos implements Stringable, DBPrimaryPos {
/**
* @param string $id GTID
* @return string[]|null (domain ID, event number, source server ID) for MariaDB,
* (source server UUID, event number, source server UUID) for MySQL, or null
* @return string[]|null (domain ID, event number, source server ID, style) for MariaDB,
* (source server UUID, event number, source server UUID, style) for MySQL, or null
*/
protected static function parseGTID( $id ) {
$m = [];
@ -270,6 +264,7 @@ class MySQLPrimaryPos implements Stringable, DBPrimaryPos {
$channelId = $m[1];
$originServerId = $m[2];
$eventNumber = $m[3];
$style = self::GTID_MARIA;
} elseif ( preg_match( '!^(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}):(?:\d+-|)(\d+)$!', $id, $m ) ) {
// MySQL style: "<server UUID>:<64 bit event number>[-<64 bit event number>]".
// Normally, the first number should reflect the point (gtid_purged) where older
@ -278,11 +273,12 @@ class MySQLPrimaryPos implements Stringable, DBPrimaryPos {
$channelId = $m[1];
$originServerId = $m[1];
$eventNumber = $m[2];
$style = self::GTID_MYSQL;
} else {
return null;
}
return [ $channelId, $eventNumber, $originServerId ];
return [ $channelId, $eventNumber, $originServerId, $style ];
}
/**