Salvaging a broken database
This chapter deals with the situation that the database for some reason is broken, and suggests some steps towards recovery.
Table of contents
Introduction
Date: Sun, 19 Apr 2020 07:37:57 +0200 (CEST) From: mdadm monitoringTo: root@bar.nemo-project.org Subject: DegradedArray event on /dev/md/0:pvn.no This is an automatically generated mail message from mdadm running on pvn.no A DegradedArray event had been detected on md device /dev/md/0. Faithfully yours, etc. P.S. The /proc/mdstat file currently contains the following: Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 sda1[0] 488253248 blocks super 1.2 [2/1] [U_] unused devices:
Databases break. This may, for instance, happen if there is no space left on the device. The error message will typically look like this:
PDOException: SQLSTATE[HY000] [2002] No such file or directory in \ lock_may_be_available() (line 167 of …/includes/lock.inc).
Try this first
You may be able to fix this by stopping and restarting the server
$ sudo systemctl stop mysql $ sudo systemctl start mysql
Recovering the InnoDB files
If the mysql server fails to start, you may need to reinstall it,
and the recover the binary InnoDB files that live under /var/lib/mysql
.
InnoDB is the current a storage engine for MySQL. It replaced MyISAM in distribution 5.5.5 in 2010.
First, make sure that mysql on your production site is unable to start. You can check the status if the mysql service with:
$ sudo service mysql status
Before you do anything, make a backup of
the /var/lib/mysql/
directory on your production
server. It is usually huge, so make sure there is space on the
destination partition.
$ sudo mkdir /home/username/mysql/ $ cd /var/lib/mysql/ $ sudo cp -R * /home/username/mysql/
You should not use the mysql server on your production site to recover these files on a staging site. Note that there is no need to run a CMS on the staging site, as everything is done using the CLI. Instead create a mirror of the backup directory on a staging server. Log on to the staging server and use this command:
$ rsync -r user@production.com:/home/username/mysql /home/username
Before you start the recovery process, you should clean up the broken mysql on the production server. This entails purging all mysql packages. If the mysql server is running, stop it first. Purging with the server still running may break things.
$ sudo systemctl stop mysql $ sudo apt purge mysql-server mysql-client mysql-common $ sudo apt purge mysql-server-core-* mysql-client-core-*
After a clean purge, remove all the mysql-related folders (make sure you have a backup copy of /var/lib/mysql
).
$ sudo rm -rf /etc/mysql $ sudo rm -rf /var/lib/mysql
Then reinstall the MySQL server fron scratch.
$ sudo apt install mysql-server
A full reinstall requires about 154 Mbyte of space. If it announces that less is required, some scraps remain. The only cure I've spotted for this is to keep purging until all packages are gone. If purging fails, running this may sometimes be helpful.
$ sudo apt-get --fix-broken install
Sources: AskUbuntu, StackOverflow.
Now, make sure that you also have a clean install of mysql on the staging server. Before starting to recover, you must stop the MySQL server gto configure recover mode:
$ sudo systemctl stop mysql
Change directory to the backup pf the InnoDB files
that you synced to the staging server and copy just the system
database folders (mysql
and sys
)
to /var/lib/mysql
. Then also copy the innodb dictionary
and other innodb-files. Set correct ownership for these files. Make
sure that /var/log/mysql/
exists and is writeable by the
database user (mysql). Do not delete the files that already exist
in /var/lib/mysql
.
$ cd /home/username/mysql $ sudo cp -R mysql /var/lib/mysql $ sudo cp -R sys /var/lib/mysql $ sudo cp ib* /var/lib/mysql $ sudo chown -R mysql.mysql /var/lib/mysql
Edit the MySQL configuration file (often /etc/mysql/mysql.cnf
) and add the
following in the [mysqld]
section at the end of file:
[mysqld] innodb_force_recovery=3
You may need to use a higher number to be able to recover anything.
(I haven't have time to investigate extensively, but 5 seems to work OK.)
You might also need to add the section
title ([mysqld]
).
Maximum
supported value of innodb_force_recovery
is 6. Values of
4 or greater can permanently corrupt data files! Use at your own risk
and only if you do not have a backup.
Now is the time to attempt to start the MySQL server again.
$ sudo systemctl start mysql
If the server starts up and stays up you can use mysqldump to dump your databases. If it does not start up you have to increase the above value of 1 stepwise.
If you look at /var/log/mysql/error.log
you might
still see errors. However try if you are able to log in to mysql:
$ mysql -u root -p Enter password: Welcome … mysql> show databases … mysql> quit Bye $
If this works, you can start recovering production databases.
$ mysqldump -u root -p database > database.sql
You can import these dumps into a production database (i.e. one that is not configured to force recovery).
$ mysql -u root -p database < database.sql
Final word
[TBA]
Last update: 2020-02-28 [gh].