web-dev-qa-db-ja.com

レプリケーションを使用して大きなテーブルからデータを削除する

all指定されたテーブルから行を削除する必要があります。テーブルには数百万またはレコードが含まれています。マスターデータベースが複数のスレーブに複製されているので、レプリケーションラグを作成したり、パフォーマンスに影響を与えたりせずにそれを実行したいと考えています。

少し調べてから、テーブルを落としてみました。それにはかなり長い時間がかかり、その間私のマスターDBはロックアウトされました。

私はより小さなバッチで徐々に削除できることを知っていますが、もっと速い方法があるのだろうと思っています。

ありがとう、Z

6
zvikico

TRUNCATE TABLE(テーブルにアクセスするすべての接続をロックします)、テーブルの空のコピーを作成し、それをスワップインして、古いテーブルを削除します。

テーブルがmydb.mytable。このようにしてください

USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
DROP TABLE mytable_old;

このようにして、mytableをすぐに空にして、データの削除中にロ​​ックされないようにします。これで、これはマスターですぐに実行され、複製されるはずです。最後の行DROP TABLE mytable_old;は最も時間がかかる可能性があります。それがあなたに関係しているなら、これをマスターとスレーブの両方で実行してください( Jynusからの回答 に基づいて)

SET sql_log_bin = 0;
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
DROP TABLE mytable_old;
SET sql_log_bin = 1;

試してみる !!!

警告

小さなチャンクでデータを削除することに関しては、テーブルデータが削除された直後にテーブルを利用できるようにする必要がある場合、それは良い考えではありません。どうして ?

  • やっているDELETE FROM mytable.mytable;は単一のトランザクションです。 InnoDBアーキテクチャでは、すべての行がロールバックのために準備されます。 DELETEが完了したら、MVCC情報をすべて破棄する必要があります。これが、なぜこんなに時間がかかるのかを説明しています。
  • 小さなチャンクで削除すると、より多くのトランザクションと小さなロールバックが作成されます。それにもかかわらず、それでも同じ量のロールバック情報と作業が作成されます。削除するデータの量を監視できる場合があります。
  • 実行しないでくださいDELETE FROM mydb.mytable LIMIT 1000;LIMIT句なしでDELETEに対してWHEREを使用すると、レプリケーションが安全ではありません。
7
RolandoMySQLDBA

TRUNCATE TABLEDELETE FROMよりも明らかに高速ですが、小さなチャンクでレコードを削除することに固執します。 TRUNCATE TABLEは、バックグラウンドで多くのことが行われているために、まだ遅くなることがあります。ディクショナリの排他ロックを取得する必要があります。ibdファイルを削除して再作成する必要があり、ページを削除する必要がありますバッファプールから。 pt-archiver を使用すると、非常に簡単です。スレーブが遅れることはありません。突然のフラッシュスパイクなどがなく、元に戻すセグメントが膨張しません。

5
akuzminsky

TRUNCATE TABLEを使用します(これにより、テーブルを削除してロールバックできない方法で再作成することにより、可能な限り最速でテーブルが空になります。

これに時間がかかりすぎる場合(innodb_file_per_tableを使用する古いバージョンのmysqlで発生する可能性があります)、マスターと各スレーブで独立して実行できます。

SET sql_log_bin = 0;

根本的なバグはおそらくこれです: http://www.percona.com/blog/2011/04/20/drop-table-performance/

4
jynus