I have three servers in a multi-master Galera cluster. I've imported some old databases recently, and noticed that the tables were being created across all three, but the data wasn't being replicated. It turns out I wasn't paying attention, and these old databases were all using MyISAM tables. So I know that in the future, I'll need to convert these to InnoDB before bringing them in to make them work.

However, I'm not having any luck finding an official way to sync up the existing data. Running ALTER TABLE to convert the existing tables to InnoDB doesn't sync up the existing data.

My thought was to dump the table (now that it's been converted) with mysqldump, then bring it back in with mysql -u user -p db < db.sql. I don't see any reason why that wouldn't work, but I'm wondering if there's a better way.


I was not able to find an official way to handle this, so I went with the idea of dumping the tables individually and reimporting them. Not wanting to do it by hand, I whipped a PHP script to do it for me. I'm posting it here in case anyone else finds this useful.

 * 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'],
    } catch ( PDOException $e ) {
        echo 'Connection failed: ' . $e->getMessage();

// Get list of databases
    $db_query = <<<SQL
    $db_result = $pdo->prepare( $db_query );

    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
            $table_result = $pdo->prepare( $table_query );

            while ( $table_row = $table_result->fetch( PDO::FETCH_ASSOC )) {
            // Loop through all tables
                $table = $table_row["Tables_in_{$db_row['Database']}"];

                $engine_query = <<<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
                    $change_result = $pdo->prepare( $change_query );

                    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";

I successfully used it to convert hundreds of tables across a couple dozen databases in about two minutes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.