MariaDB, or MySQL is stuck in the startup loop with a vague error: “Starting mysqld daemon with databases from /config/databases”. In fact, it is an error, where the InnoDB portion encountered corrupt data / tables.

What was the reason for it and how to resolve this issue? Read on.

The problem

I’m lazy. I’m impatient. I don’t document stuff, that I just play with. And so, I did not document the correct naming scheme for my DB docker containers. And so it happened, that I scaled up a production, non-cluster enabled, single instance MariaDB to a total number of 3. Guess what? I corrupted my DB. The problem did not appear right away, it took some time, but I got this:

p_db.1.9j4hoc3ck4e1@swarm3    | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [s6-init] ensuring user provided files have correct perms...exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [fix-attrs.d] applying ownership & permissions fixes...
p_db.1.9j4hoc3ck4e1@swarm3    | [fix-attrs.d] done.
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] executing container initialization scripts...
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 01-envfile: executing... 
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 01-envfile: exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 10-adduser: executing... 
p_db.1.9j4hoc3ck4e1@swarm3    | usermod: no changes
p_db.1.9j4hoc3ck4e1@swarm3    | 
p_db.1.9j4hoc3ck4e1@swarm3    | -------------------------------------
p_db.1.9j4hoc3ck4e1@swarm3    |           _         ()
p_db.1.9j4hoc3ck4e1@swarm3    |          | |  ___   _    __
p_db.1.9j4hoc3ck4e1@swarm3    |          | | / __| | |  /  \ 
p_db.1.9j4hoc3ck4e1@swarm3    |          | | \__ \ | | | () |
p_db.1.9j4hoc3ck4e1@swarm3    |          |_| |___/ |_|  \__/
p_db.1.9j4hoc3ck4e1@swarm3    | 
p_db.1.9j4hoc3ck4e1@swarm3    | 
p_db.1.9j4hoc3ck4e1@swarm3    | Brought to you by linuxserver.io
p_db.1.9j4hoc3ck4e1@swarm3    | -------------------------------------
p_db.1.9j4hoc3ck4e1@swarm3    | 
p_db.1.9j4hoc3ck4e1@swarm3    | To support LSIO projects visit:
p_db.1.9j4hoc3ck4e1@swarm3    | https://www.linuxserver.io/donate/
p_db.1.9j4hoc3ck4e1@swarm3    | -------------------------------------
p_db.1.9j4hoc3ck4e1@swarm3    | GID/UID
p_db.1.9j4hoc3ck4e1@swarm3    | -------------------------------------
p_db.1.9j4hoc3ck4e1@swarm3    | 
p_db.1.9j4hoc3ck4e1@swarm3    | User uid:    911
p_db.1.9j4hoc3ck4e1@swarm3    | User gid:    911
p_db.1.9j4hoc3ck4e1@swarm3    | -------------------------------------
p_db.1.9j4hoc3ck4e1@swarm3    | 
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 10-adduser: exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 30-config: executing... 
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 30-config: exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 40-initialise-db: executing... 
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 40-initialise-db: exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 99-custom-scripts: executing... 
p_db.1.9j4hoc3ck4e1@swarm3    | [custom-init] no custom files found exiting...
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] 99-custom-scripts: exited 0.
p_db.1.9j4hoc3ck4e1@swarm3    | [cont-init.d] done.
p_db.1.9j4hoc3ck4e1@swarm3    | [services.d] starting services
p_db.1.9j4hoc3ck4e1@swarm3    | [services.d] done.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:22:27 mysqld_safe Logging to syslog.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:22:27 mysqld_safe Starting mysqld daemon with databases from /config/databases
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:23:00 mysqld_safe Logging to syslog.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:23:00 mysqld_safe Starting mysqld daemon with databases from /config/databases
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:23:33 mysqld_safe Logging to syslog.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:23:33 mysqld_safe Starting mysqld daemon with databases from /config/databases
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:24:06 mysqld_safe Logging to syslog.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:24:06 mysqld_safe Starting mysqld daemon with databases from /config/databases
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:24:39 mysqld_safe Logging to syslog.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:24:39 mysqld_safe Starting mysqld daemon with databases from /config/databases
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:25:12 mysqld_safe Logging to syslog.
p_db.1.9j4hoc3ck4e1@swarm3    | 210125 12:25:12 mysqld_safe Starting mysqld daemon with databases from /config/databases

This keeps on looping over and over again, as the daemon tries to start an SQL instance, but something is not quite right and it fails over and over again.

After some time, I kindof figured out, that it might be corruption of the tablespaces, or something similar, beats me. I did not have proper logging set up, as I figured out later. Yeah, docker…

The proposed solution

Once almost figured out what theproblem might be, I resorted to looking through https://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html where I found a hint of a way to make a backup of the data. The fact, that I will have to do that manually did not hurt that much, but the process is not that simple. First of all, putting the Innodb to recovery. There are different levels for that. Nothing lower than 6 worked for me, so I set

[mysqld] 
innodb_force_recovery = 6

in the /config/custom.cnf

My MySQL runs on NFS, so I have the complete directory of /config mounted from outside. This includes data, configuration and logs.

After the recovery is set, the proposed solution is to make a DB dump and then recover the data in a new fresh install. Well, not quite for me. All I got were errors – possibly connected to the corruption itself

Lost connection to MySQL server during query when dumping table `wp_comments`...

and

mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */...

The real solution that worked for me

As a dump of the whole database was not possible for me, but I could clearly list the contents of the whole database, all I did was to find all the tables in my database:

# to connect to the mysql docker container
docker exec -it 2c6effa01d73 /bin/bash 

cd /config

# connect to mysql and list the tables
mysql -u <user> -p
MariaDB [(none)]> use mydatabase
MariaDB [mydatabase]> show tables;
+-----------------------+
| Tables_in_mydatabase  |
+-----------------------+
| wp_commentmeta        |
| wp_comments           |
| wp_links              |
| wp_options            |
| wp_postmeta           |
| wp_posts              |
| wp_term_relationships |
| wp_term_taxonomy      |
| wp_termmeta           |
| wp_terms              |
| wp_usermeta           |
| wp_users              |
+-----------------------+
12 rows in set (0.001 sec)

OK, got the list of all tables, cool. Now let’s try to save each single one.

tables='wp_commentmeta       
wp_comments          
wp_links             
wp_options           
wp_postmeta          
wp_posts             
wp_term_relationships
wp_term_taxonomy     
wp_termmeta          
wp_terms             
wp_usermeta          
wp_users'

for table in $tables; do mysqldump -u user -p mydatabase $table > mydatabase.$table.dmp
# depending on your setup, you might need to type in a password several times, or specify it in the command itself

ls
-rw-r--r-- 1 abc  abc     3802 Jan 25 13:10 custom.cnf
drwxr-xr-x 1 abc  abc      260 Jan 25 13:11 databases
drwxr-xr-x 1 abc  abc       10 Jan 25 13:10 log
-rw-r--r-- 1 abc  abc     3397 Jan 25 13:07 mydatabase.wp_commentmeta.dmp
-rw-r--r-- 1 abc  abc    17412 Jan 25 13:07 mydatabase.wp_comments.dmp
-rw-r--r-- 1 abc  abc     2797 Jan 25 13:07 mydatabase.wp_links.dmp
-rw-r--r-- 1 abc  abc   571141 Jan 25 13:07 mydatabase.wp_options.dmp
-rw-r--r-- 1 abc  abc   910387 Jan 25 13:07 mydatabase.wp_postmeta.dmp
-rw-r--r-- 1 abc  abc   294184 Jan 25 13:07 mydatabase.wp_posts.dmp
-rw-r--r-- 1 abc  abc     2191 Jan 25 13:07 mydatabase.wp_termmeta.dmp
-rw-r--r-- 1 abc  abc     4193 Jan 25 13:07 mydatabase.wp_term_relationships.dmp
-rw-r--r-- 1 abc  abc     4948 Jan 25 13:07 mydatabase.wp_terms.dmp
-rw-r--r-- 1 abc  abc     5126 Jan 25 13:07 mydatabase.wp_term_taxonomy.dmp
-rw-r--r-- 1 abc  abc     3989 Jan 25 13:07 mydatabase.wp_usermeta.dmp
-rw-r--r-- 1 abc  abc     2852 Jan 25 13:07 mydatabase.wp_users.dmp

I should now have all the files with table dumps in my /config directory. Let’s do the ugly part. Stop the docker container, move the DB files away from /config/databases. This path should now be empty.

Remove the line about innodb recovery mode from /config/custom.cnf or comment it out.

# innodb_force_recovery = 6

Start docker container, I should see a clean startup. This time, my DB container is named spoton_cz_DB 🙂 As you can see, there is some config t be desired, specifically for the root user, but more on that later.

spoton_cz_db.1.m0z67958dx89@swarm2    | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [s6-init] ensuring user provided files have correct perms...exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [fix-attrs.d] applying ownership & permissions fixes...
spoton_cz_db.1.m0z67958dx89@swarm2    | [fix-attrs.d] done.
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] executing container initialization scripts...
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 01-envfile: executing... 
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 01-envfile: exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 10-adduser: executing... 
spoton_cz_db.1.m0z67958dx89@swarm2    | usermod: no changes
spoton_cz_db.1.m0z67958dx89@swarm2    | 
spoton_cz_db.1.m0z67958dx89@swarm2    | -------------------------------------
spoton_cz_db.1.m0z67958dx89@swarm2    |           _         ()
spoton_cz_db.1.m0z67958dx89@swarm2    |          | |  ___   _    __
spoton_cz_db.1.m0z67958dx89@swarm2    |          | | / __| | |  /  \ 
spoton_cz_db.1.m0z67958dx89@swarm2    |          | | \__ \ | | | () |
spoton_cz_db.1.m0z67958dx89@swarm2    |          |_| |___/ |_|  \__/
spoton_cz_db.1.m0z67958dx89@swarm2    | 
spoton_cz_db.1.m0z67958dx89@swarm2    | 
spoton_cz_db.1.m0z67958dx89@swarm2    | Brought to you by linuxserver.io
spoton_cz_db.1.m0z67958dx89@swarm2    | -------------------------------------
spoton_cz_db.1.m0z67958dx89@swarm2    | 
spoton_cz_db.1.m0z67958dx89@swarm2    | To support LSIO projects visit:
spoton_cz_db.1.m0z67958dx89@swarm2    | https://www.linuxserver.io/donate/
spoton_cz_db.1.m0z67958dx89@swarm2    | -------------------------------------
spoton_cz_db.1.m0z67958dx89@swarm2    | GID/UID
spoton_cz_db.1.m0z67958dx89@swarm2    | -------------------------------------
spoton_cz_db.1.m0z67958dx89@swarm2    | 
spoton_cz_db.1.m0z67958dx89@swarm2    | User uid:    911
spoton_cz_db.1.m0z67958dx89@swarm2    | User gid:    911
spoton_cz_db.1.m0z67958dx89@swarm2    | -------------------------------------
spoton_cz_db.1.m0z67958dx89@swarm2    | 
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 10-adduser: exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 30-config: executing... 
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 30-config: exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 40-initialise-db: executing... 
spoton_cz_db.1.m0z67958dx89@swarm2    | Setting Up Initial Databases
spoton_cz_db.1.m0z67958dx89@swarm2    | Installing MariaDB/MySQL system tables in '/config/databases' ...
....
....
....
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 40-initialise-db: exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 99-custom-scripts: executing... 
spoton_cz_db.1.m0z67958dx89@swarm2    | [custom-init] no custom files found exiting...
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] 99-custom-scripts: exited 0.
spoton_cz_db.1.m0z67958dx89@swarm2    | [cont-init.d] done.
spoton_cz_db.1.m0z67958dx89@swarm2    | [services.d] starting services
spoton_cz_db.1.m0z67958dx89@swarm2    | [services.d] done.
spoton_cz_db.1.m0z67958dx89@swarm2    | 210125 13:11:04 mysqld_safe Logging to syslog.
spoton_cz_db.1.m0z67958dx89@swarm2    | 210125 13:11:04 mysqld_safe Starting mysqld daemon with databases from /config/databases

Then once again, connect to the instance and restore the tables with

root@2c6effa01d73:/config/databases# mysql -u ventil -p spotoncz < spotoncz.wp_commentmeta.dmp

For each table, mind you. And. DONE. You have a fresh DB, no corruption and the data have been saved. All data for a wordpress site, including users, passwords, comments, pages and what not are not lost forever.

Cheers.