Update to fix replication that broke with MySQL 8.4.0 removal of master and slave commands (#19153)

* Change to supported MySQL 8.4 commands

updated removed master and slave commands with the now supported commands

Signed-off-by: Duane Morris <duane.morris@cambiahealth.com>
Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>

* Add backwards compatibility

Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>

---------

Signed-off-by: Duane Morris <duane.morris@cambiahealth.com>
Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
Co-authored-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
This commit is contained in:
Duane Morris 2024-10-23 19:07:55 -07:00 committed by GitHub
parent bad51f0142
commit 7280713fcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 129 additions and 40 deletions

View File

@ -2351,6 +2351,12 @@ class DatabaseInterface implements DbalInterface
return $this->versionComment;
}
/** Whether connection is MySQL */
public function isMySql(): bool
{
return ! $this->isMariaDb;
}
/**
* Whether connection is MariaDB
*/

View File

@ -699,6 +699,9 @@ interface DbalInterface
*/
public function getVersionComment(): string;
/** Whether connection is MySQL */
public function isMySql(): bool;
/**
* Whether connection is MariaDB
*/

View File

@ -62,6 +62,10 @@ class Replication
return -1;
}
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
return $dbi->tryQuery($action . ' REPLICA ' . $control . ';', $link);
}
return $dbi->tryQuery($action . ' SLAVE ' . $control . ';', $link);
}
@ -95,16 +99,29 @@ class Replication
$this->replicaControl('STOP', null, $link);
}
$out = $dbi->tryQuery(
'CHANGE MASTER TO ' .
'MASTER_HOST=\'' . $host . '\',' .
'MASTER_PORT=' . ($port * 1) . ',' .
'MASTER_USER=\'' . $user . '\',' .
'MASTER_PASSWORD=\'' . $password . '\',' .
'MASTER_LOG_FILE=\'' . $pos['File'] . '\',' .
'MASTER_LOG_POS=' . $pos['Position'] . ';',
$link
);
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
$out = $dbi->tryQuery(
'CHANGE REPLICATION SOURCE TO ' .
'SOURCE_HOST=\'' . $host . '\',' .
'SOURCE_PORT=' . ($port * 1) . ',' .
'SOURCE_USER=\'' . $user . '\',' .
'SOURCE_PASSWORD=\'' . $password . '\',' .
'SOURCE_LOG_FILE=\'' . $pos['File'] . '\',' .
'SOURCE_LOG_POS=' . $pos['Position'] . ';',
$link
);
} else {
$out = $dbi->tryQuery(
'CHANGE MASTER TO ' .
'MASTER_HOST=\'' . $host . '\',' .
'MASTER_PORT=' . ($port * 1) . ',' .
'MASTER_USER=\'' . $user . '\',' .
'MASTER_PASSWORD=\'' . $password . '\',' .
'MASTER_LOG_FILE=\'' . $pos['File'] . '\',' .
'MASTER_LOG_POS=' . $pos['Position'] . ';',
$link
);
}
if ($start) {
$this->replicaControl('START', null, $link);
@ -158,7 +175,12 @@ class Replication
{
global $dbi;
$data = $dbi->fetchResult('SHOW MASTER STATUS', null, null, $link);
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
$data = $dbi->fetchResult('SHOW BINARY LOG STATUS', null, null, $link);
} else {
$data = $dbi->fetchResult('SHOW MASTER STATUS', null, null, $link);
}
$output = [];
if (! empty($data)) {

View File

@ -76,7 +76,11 @@ class ReplicationGui
if (! isset($_POST['repl_clear_scr'])) {
$primaryStatusTable = $this->getHtmlForReplicationStatusTable('primary', true, false);
$replicas = $dbi->fetchResult('SHOW SLAVE HOSTS', null, null);
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
$replicas = $dbi->fetchResult('SHOW REPLICAS', null, null);
} else {
$replicas = $dbi->fetchResult('SHOW SLAVE HOSTS', null, null);
}
$urlParams = $GLOBALS['urlParams'];
$urlParams['primary_add_user'] = true;
@ -126,13 +130,31 @@ class ReplicationGui
): string {
global $dbi;
$serverReplicaMultiReplication = $dbi->fetchResult('SHOW ALL SLAVES STATUS');
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
$serverReplicaMultiReplication = $dbi->fetchResult('SHOW ALL REPLICAS STATUS');
} else {
$serverReplicaMultiReplication = $dbi->fetchResult('SHOW ALL SLAVES STATUS');
}
$isReplicaIoRunning = false;
$isReplicaSqlRunning = false;
if ($serverReplicaStatus) {
$urlParams = $GLOBALS['urlParams'];
$urlParams['sr_take_action'] = true;
$urlParams['sr_replica_server_control'] = true;
if ($serverReplicaReplication[0]['Slave_IO_Running'] === 'No') {
$isReplicaIoRunning = isset($serverReplicaReplication[0]['Slave_IO_Running'])
&& $serverReplicaReplication[0]['Slave_IO_Running'] !== 'No'
|| isset($serverReplicaReplication[0]['Replica_IO_Running'])
&& $serverReplicaReplication[0]['Replica_SQL_Running'] !== 'No';
$isReplicaSqlRunning = isset($serverReplicaReplication[0]['Slave_SQL_Running'])
&& $serverReplicaReplication[0]['Slave_SQL_Running'] !== 'No'
|| isset($serverReplicaReplication[0]['Replica_SQL_Running'])
&& $serverReplicaReplication[0]['Replica_SQL_Running'] !== 'No';
if (! $isReplicaIoRunning) {
$urlParams['sr_replica_action'] = 'start';
} else {
$urlParams['sr_replica_action'] = 'stop';
@ -141,7 +163,7 @@ class ReplicationGui
$urlParams['sr_replica_control_param'] = 'IO_THREAD';
$replicaControlIoLink = Url::getCommon($urlParams, '', false);
if ($serverReplicaReplication[0]['Slave_SQL_Running'] === 'No') {
if (! $isReplicaSqlRunning) {
$urlParams['sr_replica_action'] = 'start';
} else {
$urlParams['sr_replica_action'] = 'stop';
@ -150,10 +172,7 @@ class ReplicationGui
$urlParams['sr_replica_control_param'] = 'SQL_THREAD';
$replicaControlSqlLink = Url::getCommon($urlParams, '', false);
if (
$serverReplicaReplication[0]['Slave_IO_Running'] === 'No'
|| $serverReplicaReplication[0]['Slave_SQL_Running'] === 'No'
) {
if (! $isReplicaIoRunning || ! $isReplicaSqlRunning) {
$urlParams['sr_replica_action'] = 'start';
} else {
$urlParams['sr_replica_action'] = 'stop';
@ -177,9 +196,6 @@ class ReplicationGui
$reconfigurePrimaryLink = Url::getCommon($urlParams, '', false);
$replicaStatusTable = $this->getHtmlForReplicationStatusTable('replica', true, false);
$replicaIoRunning = $serverReplicaReplication[0]['Slave_IO_Running'] !== 'No';
$replicaSqlRunning = $serverReplicaReplication[0]['Slave_SQL_Running'] !== 'No';
}
return $this->template->render('server/replication/replica_configuration', [
@ -188,8 +204,8 @@ class ReplicationGui
'primary_connection' => $_POST['primary_connection'] ?? '',
'server_replica_status' => $serverReplicaStatus,
'replica_status_table' => $replicaStatusTable ?? '',
'replica_sql_running' => $replicaSqlRunning ?? false,
'replica_io_running' => $replicaIoRunning ?? false,
'replica_sql_running' => $isReplicaIoRunning,
'replica_io_running' => $isReplicaSqlRunning,
'replica_control_full_link' => $replicaControlFullLink ?? '',
'replica_control_reset_link' => $replicaControlResetLink ?? '',
'replica_control_sql_link' => $replicaControlSqlLink ?? '',
@ -261,27 +277,33 @@ class ReplicationGui
$replicationInfo->load($_POST['primary_connection'] ?? null);
$replicationVariables = $replicationInfo->primaryVariables;
$variablesAlerts = null;
$variablesOks = null;
$variablesAlerts = [];
$variablesOks = [];
$serverReplication = $replicationInfo->getPrimaryStatus();
if ($type === 'replica') {
$replicationVariables = $replicationInfo->replicaVariables;
$variablesAlerts = [
'Slave_IO_Running' => 'No',
'Slave_SQL_Running' => 'No',
'Replica_IO_Running' => 'No',
'Replica_SQL_Running' => 'No',
];
$variablesOks = [
'Slave_IO_Running' => 'Yes',
'Slave_SQL_Running' => 'Yes',
'Replica_IO_Running' => 'Yes',
'Replica_SQL_Running' => 'Yes',
];
$serverReplication = $replicationInfo->getReplicaStatus();
}
$variables = [];
foreach ($replicationVariables as $variable) {
$serverReplicationVariable = isset($serverReplication[0])
? $serverReplication[0][$variable]
: '';
if (! isset($serverReplication[0], $serverReplication[0][$variable])) {
continue;
}
$serverReplicationVariable = $serverReplication[0][$variable];
$variables[$variable] = [
'name' => $variable,
@ -568,7 +590,12 @@ class ReplicationGui
if ($_POST['sr_replica_action'] === 'reset') {
$qStop = $this->replication->replicaControl('STOP', null, DatabaseInterface::CONNECT_USER);
$qReset = $dbi->tryQuery('RESET SLAVE;');
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
$qReset = $dbi->tryQuery('RESET REPLICA;');
} else {
$qReset = $dbi->tryQuery('RESET SLAVE;');
}
$qStart = $this->replication->replicaControl('START', null, DatabaseInterface::CONNECT_USER);
$result = $qStop !== false && $qStop !== -1 &&
@ -597,7 +624,12 @@ class ReplicationGui
}
$qStop = $this->replication->replicaControl('STOP', null, DatabaseInterface::CONNECT_USER);
$qSkip = $dbi->tryQuery('SET GLOBAL SQL_SLAVE_SKIP_COUNTER = ' . $count . ';');
if ($dbi->isMySql() && $dbi->getVersion() >= 80400) {
$qSkip = $dbi->tryQuery('SET GLOBAL SQL_REPLICA_SKIP_COUNTER = ' . $count . ';');
} else {
$qSkip = $dbi->tryQuery('SET GLOBAL SQL_SLAVE_SKIP_COUNTER = ' . $count . ';');
}
$qStart = $this->replication->replicaControl('START', null, DatabaseInterface::CONNECT_USER);
return $qStop !== false && $qStop !== -1 &&

View File

@ -21,17 +21,26 @@ final class ReplicationInfo
/** @var string[] */
public $replicaVariables = [
'Slave_IO_State',
'Replica_IO_State',
'Master_Host',
'Source_Host',
'Master_User',
'Source_User',
'Master_Port',
'Source_Port',
'Connect_Retry',
'Master_Log_File',
'Source_Log_File',
'Read_Master_Log_Pos',
'Read_Source_Log_Pos',
'Relay_Log_File',
'Relay_Log_Pos',
'Relay_Master_Log_File',
'Relay_Source_Log_File',
'Slave_IO_Running',
'Replica_IO_Running',
'Slave_SQL_Running',
'Replica_SQL_Running',
'Replicate_Do_DB',
'Replicate_Ignore_DB',
'Replicate_Do_Table',
@ -42,17 +51,25 @@ final class ReplicationInfo
'Last_Error',
'Skip_Counter',
'Exec_Master_Log_Pos',
'Exec_Source_Log_Pos',
'Relay_Log_Space',
'Until_Condition',
'Until_Log_File',
'Until_Log_Pos',
'Master_SSL_Allowed',
'Source_SSL_Allowed',
'Master_SSL_CA_File',
'Source_SSL_CA_File',
'Master_SSL_CA_Path',
'Source_SSL_CA_Path',
'Master_SSL_Cert',
'Source_SSL_Cert',
'Master_SSL_Cipher',
'Source_SSL_Cipher',
'Master_SSL_Key',
'Source_SSL_Key',
'Seconds_Behind_Master',
'Seconds_Behind_Source',
];
/** @var array */
@ -100,7 +117,11 @@ final class ReplicationInfo
private function setPrimaryStatus(): void
{
$this->primaryStatus = $this->dbi->fetchResult('SHOW MASTER STATUS');
if ($this->dbi->isMySql() && $this->dbi->getVersion() >= 80400) {
$this->primaryStatus = $this->dbi->fetchResult('SHOW BINARY LOG STATUS');
} else {
$this->primaryStatus = $this->dbi->fetchResult('SHOW MASTER STATUS');
}
}
public function getPrimaryStatus(): array
@ -110,7 +131,11 @@ final class ReplicationInfo
private function setReplicaStatus(): void
{
$this->replicaStatus = $this->dbi->fetchResult('SHOW SLAVE STATUS');
if ($this->dbi->isMySql() && $this->dbi->getVersion() >= 80400) {
$this->replicaStatus = $this->dbi->fetchResult('SHOW REPLICA STATUS');
} else {
$this->replicaStatus = $this->dbi->fetchResult('SHOW SLAVE STATUS');
}
}
public function getReplicaStatus(): array
@ -120,7 +145,11 @@ final class ReplicationInfo
private function setMultiPrimaryStatus(): void
{
$this->multiPrimaryStatus = $this->dbi->fetchResult('SHOW ALL SLAVES STATUS');
if ($this->dbi->isMySql() && $this->dbi->getVersion() >= 80400) {
$this->multiPrimaryStatus = $this->dbi->fetchResult('SHOW ALL REPLICAS STATUS');
} else {
$this->multiPrimaryStatus = $this->dbi->fetchResult('SHOW ALL SLAVES STATUS');
}
}
private function setDefaultPrimaryConnection(string $connection): void

View File

@ -12194,8 +12194,10 @@
<code>$output['File']</code>
<code>$output['Position']</code>
</MixedAssignment>
<MixedOperand occurrences="2">
<MixedOperand occurrences="4">
<code>$pos['File']</code>
<code>$pos['File']</code>
<code>$pos['Position']</code>
<code>$pos['Position']</code>
</MixedOperand>
<MoreSpecificReturnType occurrences="1">
@ -12223,11 +12225,6 @@
<code>$urlParams</code>
<code>$urlParams</code>
</MixedArgumentTypeCoercion>
<MixedArrayAccess occurrences="3">
<code>$serverReplicaReplication[0]['Slave_IO_Running']</code>
<code>$serverReplicaReplication[0]['Slave_SQL_Running']</code>
<code>$serverReplication[0][$variable]</code>
</MixedArrayAccess>
<MixedArrayAssignment occurrences="18">
<code>$_SESSION['replication']['m_correct']</code>
<code>$_SESSION['replication']['m_correct']</code>