
Ich habe drei Server in einem Multimaster-Galera-Cluster. Ich habe kürzlich einige alte Datenbanken importiert und dabei festgestellt, dass die Tabellen in allen drei erstellt wurden, die Daten jedoch nicht repliziert wurden. Es stellte sich heraus, dass ich nicht aufgepasst hatte und diese alten Datenbanken alle MyISAM-Tabellen verwendeten. Ich weiß also, dass ich diese in Zukunft in InnoDB konvertieren muss, bevor ich sie einführe, damit sie funktionieren.
Ich habe jedoch kein Glück bei der Suche nach einer offiziellen Möglichkeit, die vorhandenen Daten zu synchronisieren. Beim ALTER TABLE
Konvertieren der vorhandenen Tabellen in InnoDB werden die vorhandenen Daten nicht synchronisiert.
Mein Gedanke war, die Tabelle (nachdem sie konvertiert wurde) mit zu sichern und mysqldump
sie dann mit wieder zu importieren mysql -u user -p db < db.sql
. Ich sehe keinen Grund, warum das nicht funktionieren sollte, frage mich aber, ob es einen besseren Weg gibt.
Antwort1
Ich konnte keine offizielle Methode finden, dies zu handhaben, also habe ich mir überlegt, die Tabellen einzeln zu sichern und sie dann erneut zu importieren. Da ich das nicht von Hand machen wollte, habe ich ein PHP-Skript erstellt, das das für mich erledigt. Ich poste es hier, falls es jemand anderes nützlich findet.
/*
* InnoDB Convert
* Converts existing non-InnoDB tables to InnoDB, then re-imports the
* data so that it's replicated across the cluster.
*/
// Configuration
$_config['db'] = array(
'type' => 'mysql',
'host' => 'localhost',
'username' => 'user',
'password' => 'password'
);
// Establish database connection
try {
$pdo = new PDO(
$_config['db']['type'] . ':host=' . $_config['db']['host'],
$_config['db']['username'],
$_config['db']['password']
);
} catch ( PDOException $e ) {
echo 'Connection failed: ' . $e->getMessage();
}
// Get list of databases
$db_query = <<<SQL
SHOW DATABASES
SQL;
$db_result = $pdo->prepare( $db_query );
$db_result->execute();
while ( $db_row = $db_result->fetch( PDO::FETCH_ASSOC )) {
// Look through databases, but ignores the ones that come with a
// MySQL install and shouldn't be part of the cluster
if ( !in_array( $db_row['Database'], array( 'information_schema', 'mysql', 'performance_schema', 'testdb' ))) {
$pdo->exec( "USE {$db_row['Database']}" );
$table_query = <<<SQL
SHOW TABLES
SQL;
$table_result = $pdo->prepare( $table_query );
$table_result->execute();
while ( $table_row = $table_result->fetch( PDO::FETCH_ASSOC )) {
// Loop through all tables
$table = $table_row["Tables_in_{$db_row['Database']}"];
$engine_query = <<<SQL
SHOW TABLE STATUS WHERE Name = :table
SQL;
$engine_result = $pdo->prepare( $engine_query );
$engine_result->execute( array(
':table' => $table
));
$engine_row = $engine_result->fetch( PDO::FETCH_ASSOC );
if ( $engine_row['Engine'] != 'InnoDB' ) {
// Engine is not equal to InnoDB, let's convert it
echo "Converting '$table' on '{$db_row['Database']}' from '{$engine_row['Engine']}' to InnoDB:\n";
echo "Modifying engine...";
$change_query = <<<SQL
ALTER TABLE $table ENGINE=InnoDB
SQL;
$change_result = $pdo->prepare( $change_query );
$change_result->execute();
echo "done!\n";
echo " Exporting table...";
exec( "mysqldump -h {$_config['db']['host']} -u {$_config['db']['username']} -p{$_config['db']['password']} {$db_row['Database']} $table > /tmp/dump-file.sql" );
echo "done!\n";
echo " Re-importing table...";
exec( "mysql -h {$_config['db']['host']} -u {$_config['db']['username']} -p{$_config['db']['password']} {$db_row['Database']} < /tmp/dump-file.sql" );
echo "done!\n";
unlink( '/tmp/dump-file.sql' );
echo "done!\n";
}
}
}
}
Ich habe es erfolgreich verwendet, um Hunderte von Tabellen in mehreren Dutzend Datenbanken in etwa zwei Minuten zu konvertieren.