マスターサーバーとさまざまなスレーブサーバーがあります。
すべてのサーバーに膨大な量のデータがあり、データ用のアーカイブシステムを作成したいと考えています。
シナリオは:過去1年間のデータのみがサーバー上にあり、他のすべての以前のデータがアーカイブシステムに移動されることを望みます。
ほとんどのテーブルはInnoDBであり、テーブル間に参照整合性がある場合もあります。 (アーカイブに移動したサーバーから古いデータをパージ/削除すると、参照整合性も失敗する可能性があります)。
このデータは運用サーバーにあるので、ダウンタイムなしでこれを達成するにはどのような手順を実行すればよいですか?
Percona Toolkitのpt-archiverツールを確認することをお勧めします。
これを行うためのストアドプロシージャを実際に作成しました。例を挙げて説明します。実際に2つ書いた。 1つはテーブルを作成し、もう1つはデータをコピーします。
私は、vhostidおよびmidと呼ばれるほとんどすべてのテーブルで使用される2つの「外部キー」を持っています。だからこれは私が書いたテーブルをバックアップするためにやったことです:
CREATE DEFINER = 'mydbuser'@'%' PROCEDURE `sp_create_backup_tables`()
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE table_to_create, database_name VARCHAR(255);
DECLARE backup_tables_cursor CURSOR FOR
SELECT DISTINCT (INFORMATION_SCHEMA.COLUMNS.TABLE_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
INNER JOIN INFORMATION_SCHEMA.TABLES
ON INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA = INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA
AND INFORMATION_SCHEMA.TABLES.TABLE_NAME = INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
WHERE INFORMATION_SCHEMA.TABLES.TABLE_TYPE <> 'VIEW'
AND (INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME = 'vhostid'
OR
INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME = 'mid')
AND INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA <> 'db_archive'
AND INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA LIKE 'mydbname%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE DATABASE IF NOT EXISTS db_archive;
SELECT INFORMATION_SCHEMA.SCHEMATA.SCHEMA_NAME
INTO database_name
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE INFORMATION_SCHEMA.SCHEMATA.SCHEMA_NAME LIKE 'mydbname%'
AND INFORMATION_SCHEMA.SCHEMATA.SCHEMA_NAME <> 'db_archive';
OPEN backup_tables_cursor;
create_tables_loop: LOOP
FETCH backup_tables_cursor INTO table_to_create;
IF done THEN
LEAVE create_tables_loop;
END IF;
SET @backup_table_name = CONCAT('db_archive.', table_to_create, '_archive');
SET @SQL = CONCAT('CREATE TABLE IF NOT EXISTS ', @backup_table_name, ' LIKE ', database_name, '.', table_to_create);
PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE backup_tables_cursor;
END;
したがって、これは基本的に必要なすべてのバックアップテーブルを作成します。
次のステップでは、すべてのレコードを取得します。残念ながら、現時点ではそのストアドプロシージャを見つけることはできませんが、ほとんど同じように機能します。気になるすべての行には、作成日のdatetime列があります。そのため、db_backupテーブルにあるすべてのテーブルを走査して、作成日がnow()より小さいすべての行を選択します。次に、キーテーブル、vhosts、およびメディアからすべての行IDを抽出し、それらのIDをカーソルに格納します。
次に、その外部キー関係を維持する可能性のある他のすべてのテーブルを調べ、それらの行を新しいデータベースにコピーします。大規模なデータベースではかなりCPUを集中的に使用しますが、それは機能し、トラフィックの低いポイントで夜通し実行します。
最後に、コピーした行を削除するかどうかのトリガーに渡される変数があります。削除すると、さまざまなテーブルの行が削除されます。
うまくいけば、行をコピーするために書いたストアドプロシージャが見つかればいいのですが、何らかの理由で欠落しているようです。
以下は、同様の要件のために実装したメソッドです。このセットアップには、ダウンタイムがなく、アーカイブデータベースが常に最新のデータで最新であるという利点があります。
マスターと少なくとも2つのスレーブをセットアップします。
スレーブの1つをマスターのフェイルオーバーとして指定し、もう1つのスレーブをアーカイブdbとして指定します。フェイルオーバー用の複数のスレーブと、アーカイブデータベースとして機能する複数のスレーブを使用できます。
必要に応じて、タイムスタンプ列でパーティション化された大きなテーブルを設定します。
スレーブへの変更を複製せずにデータを削除するストアドプロシージャまたはSQLスクリプトを作成します。 (このスクリプトは、必要に応じてパーティションの作成と削除も処理できます。)これは、そのトランザクションのバイナリログをオフにし、削除してから、バイナリログを再びオンにすることで実現できます。
SET sql_log_bin = 0;
-DELETEステートメント。
SET sql_log_bin = 1;
マスターでcronジョブまたはMySQLイベントスケジューラを介して、SQL削除スクリプトまたはストアドプロシージャを実行します。
アーカイブデータベースとして指定されていないスレーブサーバーごとに、上記の手順を繰り返します。
アプリケーションクエリに適切なタイムスタンプの範囲を設定してロックを防止し、クリーンアップスクリプトが実行されるときに1年以上経過したデータがクエリされないようにします。
この状況では、月ごとにパーティションを設定します。毎月、マスタースレーブと非アーカイブスレーブでストアドプロシージャを実行し、最も古いパーティションを削除して、次の月のデータ用に新しいパーティションを作成します。
おそらくまだMySQLレプリケーションを使用できます。
スレーブの1つをArchiveSlaveとして指定します。
ArchiveSlaveでは、Percona Toolkitから pt-slave-delay という特別なツールを実行する必要があります。
ドキュメントからの例です
Slavehostをマスターの1分遅れて10分間保持するには、次のようにします。
pt-slave-delay --delay 1m --interval 15s --run-time 10m slavehost
あなたの場合、あなたは毎日1日遅れてArchiveSlaveを保持したいかもしれません
pt-slave-delay --delay 24h --interval 15s --run-time 86340s slavehost
これにより、スレーブが24時間遅れて23時間59分保持されます。
真夜中にcrontabでこれを実行してみてください