How to Fix “InnoDB: Upgrade Not Supported After Crash with innodb_fast_shutdown=2” Error in MySQL 8.0


2 views

When attempting to upgrade MySQL from 8.0.29 to 8.0.30 in a Docker container, you might encounter this critical error:

2022-09-06T13:13:40.954725Z 1 [ERROR] [MY-012526] [InnoDB] Upgrade is not supported after a crash or shutdown with innodb_fast_shutdown = 2.

Even worse, attempting to roll back to the previous version (8.0.29) fails with:

2022-09-06T13:31:24.588234Z 1 [ERROR] [MY-013171] [InnoDB] Cannot boot server version 80029 on data directory built by version 80030.

The error occurs because MySQL's InnoDB engine was previously shut down with innodb_fast_shutdown=2, which performs a "cleanup" shutdown but leaves the redo logs in a state that prevents version upgrades. This is a safety mechanism to prevent data corruption.

Here's how to recover from this state:

1. Restore Original Data Directory (If Possible)

First attempt to restore from your most recent backup:

# Stop the MySQL container
docker stop mysql_container

# Replace data directory with backup
rm -rf /var/lib/mysql/*
cp -a /backup/mysql/* /var/lib/mysql/

# Start with original version
docker run --name mysql_container -v /var/lib/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=your_password -d mysql:8.0.29

2. Force Recovery Mode (If No Backup)

If you don't have a backup, try forcing recovery:

# Create custom my.cnf
echo "[mysqld]
innodb_force_recovery = 6
innodb_fast_shutdown = 0" > /etc/mysql/conf.d/recovery.cnf

# Start container with recovery config
docker run --name mysql_recovery \
  -v /etc/mysql/conf.d/recovery.cnf:/etc/mysql/conf.d/recovery.cnf \
  -v /var/lib/mysql:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=your_password \
  -d mysql:8.0.29

After successful start, immediately dump your data:

docker exec -it mysql_recovery mysqldump -u root -p --all-databases > full_backup.sql

3. Clean Install and Data Import

With your data dumped, create a fresh instance:

# Remove old data
rm -rf /var/lib/mysql/*

# Start fresh MySQL 8.0.30
docker run --name mysql_fresh \
  -v /var/lib/mysql:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=your_password \
  -d mysql:8.0.30

# Import data
docker exec -i mysql_fresh mysql -u root -p < full_backup.sql

To avoid this issue in future upgrades:

# Before upgrading, always:
SET GLOBAL innodb_fast_shutdown = 0;
SHUTDOWN;

And consider adding this to your MySQL configuration:

[mysqld]
innodb_fast_shutdown = 0

For safer upgrades, use this bash script:

#!/bin/bash
# MySQL safe upgrade script
MYSQL_USER="root"
MYSQL_PASS="your_password"
BACKUP_DIR="/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)

# Create backup
docker exec mysql_container mysqldump -u $MYSQL_USER -p$MYSQL_PASS --all-databases > $BACKUP_DIR/full_backup_$DATE.sql

# Set safe shutdown
docker exec mysql_container mysql -u $MYSQL_USER -p$MYSQL_PASS -e "SET GLOBAL innodb_fast_shutdown = 0; SHUTDOWN;"

# Wait for shutdown
sleep 10

# Start new version
docker stop mysql_container
docker rm mysql_container
docker run --name mysql_container -v /var/lib/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=$MYSQL_PASS -d mysql:8.0.30

When attempting to upgrade MySQL from 8.0.29 to 8.0.30 in a Docker environment, you might encounter two critical errors:

ERROR 1: "Upgrade is not supported after a crash or shutdown with innodb_fast_shutdown = 2"
ERROR 2: "Cannot boot server version 80029 on data directory built by version 80030"

The root cause stems from how InnoDB handles shutdowns. When innodb_fast_shutdown=2 is set, MySQL performs a "cold shutdown" that leaves the redo log in a state that prevents upgrades. This is a safety mechanism to ensure data integrity.

Here's a step-by-step approach to recover your database:

  1. Recover original data files: First, ensure you have backups of your original datadir
  2. Start with clean data:
# Create a temporary directory for recovery
mkdir -p /tmp/mysql_recovery
chown -R mysql:mysql /tmp/mysql_recovery

# Start MySQL 8.0.29 with clean initialization
docker run --rm \
  -v /tmp/mysql_recovery:/var/lib/mysql \
  -e MYSQL_ALLOW_EMPTY_PASSWORD=1 \
  mysql:8.0.29 --initialize-insecure

For the actual data recovery:

# Use mysqldump from your original container
docker exec original_mysql_container \
  mysqldump -uroot -p --all-databases > full_backup.sql

# Import into new instance
docker exec new_mysql_container \
  mysql -uroot -p < full_backup.sql

To avoid this situation in future upgrades:

  • Always set innodb_fast_shutdown=1 (default) before upgrading
  • Execute proper shutdown sequence: mysqladmin -uroot -p shutdown
  • Verify clean shutdown with: SHOW STATUS LIKE 'Innodb_shutdown_status';

If you must recover the existing data directory:

# Add these to your my.cnf under [mysqld] section
innodb_force_recovery = 6
innodb_purge_threads = 0

Start the server temporarily to dump data, then rebuild properly.

MySQL maintains strict version control on data files. Key points:

  • Major version upgrades require special procedures
  • Downgrades are generally not supported
  • Always test upgrades in staging first

For production systems, consider using MySQL Shell's upgrade checker utility:

mysqlsh -- util checkForServerUpgrade root@localhost:3306 --target-version=8.0.30