MariaDB Galera クラスター、強制同期

MariaDB Galera クラスター、強制同期

マルチマスター Galera クラスターに 3 台のサーバーがあります。最近、古いデータベースをいくつかインポートしたところ、3 台すべてでテーブルが作成されているのに、データが複製されていないことに気付きました。注意を払っていなかったため、これらの古いデータベースはすべて MyISAM テーブルを使用していたことが判明しました。そのため、将来的には、これらを InnoDB に変換してからインポートして動作させる必要があることがわかりました。

しかし、既存のデータを同期する正式な方法を見つけることができませんでした。ALTER TABLE既存のテーブルを InnoDB に変換しても、既存のデータは同期されません。

私の考えでは、テーブルを (変換されたので) でダンプしmysqldump、それを で戻すことでしたmysql -u user -p db < db.sql。それが機能しない理由は見当たりませんが、もっと良い方法があるのではないかと思っています。

答え1

これを処理する正式な方法を見つけることができなかったので、テーブルを個別にダンプして再インポートすることにしました。手動でやりたくなかったので、PHP スクリプトを作成して代わりに実行してもらいました。他の誰かの役に立つかもしれないので、ここに投稿します。

/*
 * 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";
                }
            }
        }
    }

私はこれを使用して、約 2 分で数十のデータベースにわたる数百のテーブルを変換することに成功しました。

関連情報