
Eu tenho três servidores em um cluster Galera multimestre. Importei recentemente alguns bancos de dados antigos e percebi que as tabelas estavam sendo criadas nos três, mas os dados não estavam sendo replicados. Acontece que eu não estava prestando atenção e todos esses bancos de dados antigos usavam tabelas MyISAM. Portanto, sei que, no futuro, precisarei convertê-los para InnoDB antes de trazê-los para fazê-los funcionar.
No entanto, não estou tendo sorte em encontrar uma maneira oficial de sincronizar os dados existentes. Executar ALTER TABLE
para converter as tabelas existentes para InnoDB não sincroniza os dados existentes.
Meu pensamento foi despejar a tabela (agora que ela foi convertida) mysqldump
e trazê-la de volta com mysql -u user -p db < db.sql
. Não vejo nenhuma razão para que isso não funcione, mas estou me perguntando se existe uma maneira melhor.
Responder1
Não consegui encontrar uma forma oficial de lidar com isso, então optei por descartar as tabelas individualmente e reimportá-las. Não querendo fazer isso manualmente, criei um script PHP para fazer isso por mim. Estou postando aqui caso alguém ache isso útil.
/*
* 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";
}
}
}
}
Usei-o com sucesso para converter centenas de tabelas em algumas dezenas de bancos de dados em cerca de dois minutos.