ソースデータ:
- MySQLを搭載したデータベースサーバーがあります。
- 常に満杯になっており、たとえばしばらく使用されない可能性のあるものの、破損したログのテーブル(統計)
- 毎日のバックアップ。
- 最後の日次(完全)バックアップからのバイナリログ。
チャレンジ:
- サーバーは操作に使用可能でなければなりません。
- 新しいデータがテーブルに分類されるはずです。
- データの整合性を復元します。
期待される結果:
破損したテーブルのデータは、メロンデータベースを停止せずに復元されます。
テーブルには、currentを含むすべてのデータが含まれます。
凡例:
- DB-SRV-北のデータベースあり;
- ACME_DB-「失われた」テーブルがあるデータベース。
- ACME_DB_RECOVERY-リカバリ用のデータベース、テーブルまたはデータベース。
- ACME_DB_INCREMENTAL-バイナリログから回復するためのデータベース。
- FAIL_TABLE-復元される破損したテーブル。
- ACME_DB.FAIL_TABLE.BACKUPDATE.sql-最後の完全バックアップから破損したテーブルのダンプを含むファイル。
なぜそのような庭が誇っていたのか。 また、データベースのサイズとリソースの不足のため、現在、表形式のダンプが使用されているため、バックアップ時のデータの整合性については疑問の余地はありません。
免責事項の代わりに:
- この記事は、テーブルが落ちた場合のデータ回復のための別の戦略を紹介することを目的に書かれています。 すべてのASISを使用することは強くお勧めしません。 まあ、あなた自身はあなたのデータに起こるすべてに責任があります:)
アクションプラン(回復):
現在のデータを追加する場所になるように、破損したテーブルのコピーを作成します
mysql > CREATE TABLE FAIL_TABLE_NEW LIKE FAIL_TABLE;
AUTO_INCREMENTフィールドを持つテーブルの場合、カウンターも変更します。 カウンタ値を任意の量、たとえばFAIL_TABLEテーブルの現在の値から1000ずつ増やします。
mysql> ALTER TABLE FAIL_TABLE_NEW AUTO_INCREMENT = value;
mysql > RENAME FAIL_TABLE TO FAIL_TABLE_OLD, FAIL_TABLE_NEW TO FAIL_TABLE;
補助データベースACME_DB_RECOVERYおよびACME_DB_INCREMENTALを作成します
mysql > CREATE DATABASE ACME_DB_RECOVERY;
mysql > CREATE DATABASE ACME_DB_INCREMENTAL;
パラノイアの場合:)各補助ベースのユーザーを作成することができます。
mysql > CREATE USER 'recovery'@'localhost' IDENTIFIED BY 'mypass';
mysql > CREATE USER 'increment'@'localhost' IDENTIFIED BY 'mypass';
mysql > GRANTSELECT,INSERT,UPDATE,DELETE,LOCK TABLES,SUPER,INDEX,CREATE ON ACME_DB_RECOVERY TO 'recovery'@'localhost';
mysql > GRANT SELECT,INSERT,UPDATE,DELETE,LOCK TABLES,SUPER,INDEX,CREATE ON ACME_DB_INCREMENTAL TO 'increment'@'localhost';
mysql > FLUSH PRIVILEGES;
フルバックアップから破損したテーブルを回復する
$ mysql -u recovery -p -h DB-SRV ACME_DB_RECOVERY < ACME_DB.FAIL_TABLE.BACKUPDATE.sql
次に、サーバーのdatadirに移動し、server_hostname-bin.004324という形式のファイルを見つけます。
バックアップのテーブルのデータよりも早く始まる適切なbinlogと、破損が発生するまでのデータを含むbinlogが見つかりますmysqlbinlog -d ACME_DBコマンドでバイナリログの内容を確認できます。
binlogから回復するには、完全なテーブル構造ACME_DBを作成する必要があります
$ mysqldump --no-data -u ACME_USER -p ACME_DB -h DB-SRV | mysql -h DB-SRV -u increment -p ACME_DB_INCREMENTAL
そして、バイナリログのデータを作成順に入力します。
$ mysqlbinlog -d ACME_DB < > | mysql -u increment -p ACME_DB_INCREMENTAL
次に、ダンプとバイナリログのデータを接続する必要があります。
バックアップからテーブルの最後のデータを決定します。この「瞬間」から、バイナリログから回復したテーブルのデータと一時テーブルの最初のデータを追加します。 たとえば、次のクエリでは:
mysql > USE ACME_DB;
mysql > SELECT MIN(id) FROM FAIL_TABLE; # FIRST_ID
mysql > SELECT MIN(date) FROM FAIL_TABLE; # FISRT_DATE
mysql> USE ACME_DB_RECOVERY;
mysql > SELECT MAX(id) FROM FAIL_TABLE; # LAST_ID
mysql > SELECT MAX(date) FROM FAIL_TABLE; # LAST_DATE
mysql > INSERT INTO FAIL_TABLE (SELECT * FROM ACME_DB_INCREMENTAL.FAIL_TABLE WHERE ID > LAST_ID AND ID < FIRST_ID);
#
mysql > INSERT INTO FAIL_TABLE (SELECT * FROM ACME_DB_INCREMENTAL.FAIL_TABLE WHERE DATE >= LAST_DATE AND DATE < FIRST_DATE);
したがって、データは落下の瞬間まで復元されました。今では少しのデータ転送です。例はAUTO_INCREMENTフィールドを持つテーブルの場合です。そうでない場合は、カウンターを設定して場所をスキップできます。
ACME_DB.FAIL_TABLEテーブルの現在のカウンターを見て、ACME_RECOVERY.FAIL_TABLEテーブルのACME_RECOVERY.FAIL_TABLEテーブルをもう少し設定します。これはすべて、データベースに挿入したレコードの数に依存します。数千で十分です。
mysql > USE ACME_RECOVERY;
mysql > ALTER TABLE FAIL_TABLE AUTO_INCREMENT = value;
mysql > USE ACME_DB;
mysql > RENAME TABLE FAIL_TABLE TO FAIL_TABLE_SMALL, ACME_RECOVERY.FAIL_TABLE TO ACME_DB.FAIL_TABLE;
mysql > INSERT INTO FAIL_TABLE (SELECT * FROM FAIL_TABLE_SMALL);
すべての一時データを削除します
mysql > DROP DATABASE ACME_DB_INCREMENTAL;
mysql > DROP DATABASE ACME_DB_RECOVERY;
更新:
zhirafovodは、あるデータベースが他のデータベースの変更に関するデータを取得できることを提案しました。たとえば、ACME2.TABLEを更新します
変更を回避するには、新しいデータベースとそのデータベース用に特別に作成されたユーザーに必ず特権を設定する必要があります。