⬆️ ⬇️

Recovery strategy for damaged table in MySQL

It all started with the fact that at one point the kernel killed the mysqld daemon and mysql_safe with the machine restarted and everything would be fine, but only the tables in the database were used by MyISAM. In the end, I had to use myisamcheck, but this is another story. In the process of checking and repairing indexes, one table suffered and it was decided to restore from backups, it’s good that they are done once a day.



Initial data:



Task:



Expected Result:

the data in the damaged table was restored without stopping the melon database;

the table contains all the data including the current.



Legend:





For which such a garden was proud. And all because of the size of the database and the lack of resources, a tabular dump is currently being used, so there is no talk about data integrity at the time of backup.

')

Instead of a disclaimer:





Action Plan (Recovery):



Make a copy of the damaged table so that the current data was where to put



mysql > CREATE TABLE FAIL_TABLE_NEW LIKE FAIL_TABLE;



If the table with the field AUTO_INCREMENT, then we make more changes to the counter. We increase the counter value by a little, for example, 1000 from the current value in the FAIL_TABLE table.

mysql> ALTER TABLE FAIL_TABLE_NEW AUTO_INCREMENT = value;



mysql > RENAME FAIL_TABLE TO FAIL_TABLE_OLD, FAIL_TABLE_NEW TO FAIL_TABLE;



Create auxiliary databases ACME_DB_RECOVERY and ACME_DB_INCREMENTAL



mysql > CREATE DATABASE ACME_DB_RECOVERY;

mysql > CREATE DATABASE ACME_DB_INCREMENTAL;




For paranoids :) you can do for each auxiliary base by user.



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;




We recover the damaged table from a full backup



$ mysql -u recovery -p -h DB-SRV ACME_DB_RECOVERY < ACME_DB.FAIL_TABLE.BACKUPDATE.sql



Next we go to the datadir server and find files like server_hostname-bin.004324



We find a suitable binlog that starts earlier than the data in the table from backup and binlog with data until the moment of damage, to see what can be done in the binary log using the command mysqlbin -d ACME_DB.



In order to recover from binlog, you need to create a complete ACME_DB table structure.



$ mysqldump --no-data -u ACME_USER -p ACME_DB -h DB-SRV | mysql -h DB-SRV -u increment -p ACME_DB_INCREMENTAL



And we enter data from binary logs in the order of their creation.



$ mysqlbinlog -d ACME_DB < > | mysql -u increment -p ACME_DB_INCREMENTAL



Next we need to connect the data from the dump and binary logs.



We define the latest data in the table from backup, from this “moment” we will add data from the table recovered from binary logs and the first data from the temporary table. For example, here are such queries:



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);





So, the data was restored until the moment of the fall, now we are transferring the data for small, an example will be for a table with an AUTO_INCREMENT field, if there is no such thing, you can skip the place with the installation of the counter.



We look at the current counter in the ACME_DB.FAIL_TABLE table, set the counter in the ACME_RECOVERY.FAIL_TABLE table a bit more, it all depends on how many records you have inserted into the database, a few thousand.

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);




Delete all temporary data



mysql > DROP DATABASE ACME_DB_INCREMENTAL;

mysql > DROP DATABASE ACME_DB_RECOVERY;




update:

zhirafovod prompted that the binoglog of one database can get data on other changes, for example update ACME2.TABLE ...

To avoid changes, it is necessary to set privileges for new databases and specially created for them users.

Source: https://habr.com/ru/post/122747/



All Articles