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:
- Recover original data files: First, ensure you have backups of your original datadir
- 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