MySQLの破損したテーブルのリカバリ戦略

それはすべて、ある時点でカーネルがmysqldデーモンを釘付けにし、mysql_safeが自動的に再起動し、すべてがうまくいくという事実から始まりましたが、データベース内のテーブルのみがMyISAMによって使用されました。 結局、myisamcheckを使用する必要がありましたが、これはまったく別の話です。 インデックスのチェックと修正のプロセスで、1つのテーブルが破損し、バックアップから復元することが決定されました。1日に1回行われるのは良いことです。



ソースデータ:



チャレンジ:



期待される結果:

破損したテーブルのデータは、メロンデータベースを停止せずに復元されます。

テーブルには、currentを含むすべてのデータが含まれます。



凡例:





なぜそのような庭が誇っていたのか。 また、データベースのサイズとリソースの不足のため、現在、表形式のダンプが使用されているため、バックアップ時のデータの整合性については疑問の余地はありません。



免責事項の代わりに:





アクションプラン(回復):



現在のデータを追加する場所になるように、破損したテーブルのコピーを作成します



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を更新します

変更を回避するには、新しいデータベースとそのデータベース用に特別に作成されたユーザーに必ず特権を設定する必要があります。



All Articles