InnoDBテーブルを新しいテーブルに置き換えようとしていますが、古いテーブルを指すすべての外部キー参照が新しいテーブルを指すようにします。
だから私はこれを試しました:
SET foreign_key_checks = 0;
ALTER TABLE foo RENAME foo_old;
ALTER TABLE foo_new RENAME foo;
残念ながら、foreign_key_checksが無効になっている場合でも、fooを指すすべての参照はfoo_oldを指すように変更されます。今私はどちらかを探しています
外部キーを削除して再作成してみましたが、テーブルが大きいため数時間かかります。テーブルを置き換えることの全体的なポイントは、限られたダウンタイムでスキーマを変更することでした。
古い質問ですが、次の方法が考えられます。基本的に、テーブルの名前を変更するのではなく、データを移動します。もちろん、新しいデータが外部キー規則に準拠していることを確認する必要があります。
SET foreign_key_checks = 0;
CREATE TABLE IF NOT EXISTS foo_old LIKE foo;
INSERT INTO foo_old SELECT * FROM foo;
TRUNCATE foo;
INSERT INTO foo SELECT * FROM foo_new;
これを1つのクエリとして実行して、foreign_key_checksがすべてに適用されるようにしてください。お役に立てれば。
MySQL 5.6では、innodb_file_per_table=ON
を使用すると、表スペースをその場で交換できます。ファイル操作は個別に実行する必要があるため、SQLを使用してこれを完全に実行することはできません。まず、コピーするfoo_new
テーブルを準備し、foo
データをドロップします。
SET foreign_key_checks = 0;
ALTER TABLE foo DISCARD TABLESPACE;
FLUSH TABLES foo_new FOR EXPORT;
この時点で、関連するInnoDBファイルを正しい名前にコピーする必要があります。ファイルはデータディレクトリに保存されます。たとえば、Debianでは、デフォルトで/var/lib/mysql/yourdatabase
にあり、ファイルはfoo_new.ibd
、foo_new.cfg
、およびfoo_new.frm
です。それらをそれぞれfoo.ibd
、foo.cfg
、およびfoo.frm
にコピーします。例えば:
$ cp foo_new.ibd foo.ibd
$ cp foo_new.frm foo.frm
$ cp foo_new.cfg foo.cfg
MySQLが新しいファイルにアクセスできることに注意してください(たとえば、正しい所有者、アクセス権があります)。完了したら、テーブルを再度インポートして、外部キーを有効にすることができます。
UNLOCK TABLES;
ALTER TABLE foo IMPORT TABLESPACE;
SET foreign_key_checks = 1;
これは、foo_new
をfoo
にコピーするだけです。 foo
をfoo_old
にコピーする必要がある場合は、手順を繰り返します。
残念ながら、最初に外部キーを削除して再作成しない限り、問題を回避する方法はないと思います。
これはマイナーですが、RENAME
コマンドでも何かを見つけました。それらをチェーン化することができ、すべてのステップが成功しない限り、他のすべての名前変更がロールバックされます。構文は次のとおりです。
RENAME TABLE foo TO foo_old, foo_new TO foo;
InnoDBは外部キーでテーブルの内部ポインターを使用するため、このテーブルに付けられた名前に関係なく(RENAME
を使用)、SET foreign_key_checks = 0
を使用する場合も含めて制約が保持されます。
テーブル全体を再構築せずに外部キー参照を元に戻す方法
innodb_file_per_table=ON
を使用すると、最も近い方法になります(@vhuの回答を参照)。
外部キー参照を更新せずにテーブルの名前を変更する方法。
ダウンタイムと労力を最小限に抑え、サーバーへのシェルアクセスを必要としないソリューションは、単に2つのデータベースを操作し、それらを期限内にオンにすることです、データが変更されない場合とても
大きなテーブル以外のすべてのテーブルを同期するか、変更がある場合はスイッチまでアプリケーションでmysqlコマンド(削除、更新、挿入)を一時的に複製する方がさらに高速になる可能性があります。
これを回避する方法を見つけました...名前を変更する代わりに、ソーステーブルを削除するだけです。
この例では、テーブルを「mytbl」と呼びます。
唯一の欠点は、元のテーブルのバックアップを保持できないことですが、事前にmysqldumpすることはできます。または、元のテーブルの逐語的なコピーが必要な場合は、追加のテーブルコピーを作成できます。