Fixing MariaDB column_stats upgrade error
A walkthrough of fixing a MariaDB system table schema mismatch after upgrading to 12.3.3 in Docker Compose, including the root cause and how to prevent it from happening again.
I updated my Ghost CMS Docker Compose stack from MariaDB 12.3.2 to 12.3.3. A patch bump. Nothing to worry about, right?
After restarting the containers, everything seemed fine. The blog loaded. No downtime. But when I checked the logs, I saw this:
ghost-mariadb | 2026-08-25 7:54:19 3 [ERROR] Incorrect definition of table mysql.column_stats: expected column 'hist_type' at position 9 to be nullable.
The container was running. Ghost was serving pages. But an error was sitting in the logs, and I did not like it.
The environment
My setup is a simple Docker Compose file with two services:
- ghost-app — Ghost 6.59.0 Alpine
- ghost-mariadb — MariaDB 12.3.3 Noble
The MariaDB data lives on a named Docker volume (ghost-mariadb). I was upgrading from mariadb:12.3.2-noble to mariadb:12.3.3-noble. A patch bump, so I honestly did not expect any issues.
That was the key detail.
What I ruled out first
At first I thought it might be a Ghost compatibility issue. But Ghost was running fine. Pages loaded. The API worked. Whatever was wrong, it was on the MariaDB side.
I also checked if the volume was corrupted. It was not. The data was intact, the tables were accessible. The error was specifically about a schema definition mismatch, not about data corruption.
So I dug into the logs.
What was going on
I looked at the full startup log more carefully. Two lines stood out:
[Note] [Entrypoint]: MariaDB upgrade information missing, assuming required
[Note] [Entrypoint]: MariaDB upgrade (mariadb-upgrade or creating healthcheck users) required, but skipped due to $MARIADB_AUTO_UPGRADE setting
The MariaDB entrypoint script knew the data directory needed an upgrade. But it skipped it. The MARIADB_AUTO_UPGRADE environment variable was not set in my compose file, and for whatever reason, the entrypoint chose to skip rather than run the upgrade automatically.
So the server started with system tables from 12.3.2. The mysql.column_stats table had a hist_type column defined as NOT NULL. But MariaDB 12.3.3 expected it to be nullable. The column_stats table stores histogram statistics for the query optimizer. A mismatch here means the optimizer cannot use column histograms correctly.
The server would still run. Queries would still work. But the error was there, and I did not want to leave it.
The fix
What worked for me was running mariadb-upgrade inside the container. It checks and repairs system tables, views, and privileges. The MariaDB docs have more detail on this, but the command itself is simple.
docker exec ghost-mariadb mariadb-upgrade -u root -p"<password>"
The output was long but clean. Phase 1 checked the mysql database and fixed the column_stats table immediately:
Phase 1/8: Checking and upgrading mysql database
Processing databases
mysql
mysql.column_stats OK
The rest of the phases ran through views, privilege tables, and all the Ghost application tables. Everything came back OK. No drama.
Preventing it next time
After the upgrade, I added MARIADB_AUTO_UPGRADE: 1 to the ghost-mariadb environment in my docker-compose.yaml:
ghost-mariadb:
image: mariadb:12.3.3-noble
environment:
MARIADB_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MARIADB_DATABASE: ${MYSQL_DATABASE}
MARIADB_USER: ${MYSQL_USER}
MARIADB_PASSWORD: ${MYSQL_PASSWORD}
MARIADB_AUTO_UPGRADE: 1
This tells the MariaDB entrypoint to run mariadb-upgrade automatically when it detects the data directory is from an older version. No more skipped upgrades, no more silent schema mismatches.