> ## Content Index
> Fetch the complete content index at: https://anantafatur.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Fixing MariaDB column_stats upgrade error
- URL: https://anantafatur.dev/fixing-mariadb-column-stats-upgrade-error/
- Published: 2026-08-25T08:13:32.000Z
- Updated: 2026-08-25T08:13:32.000Z
- Description: 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.
- Author: Ananta

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.

```bash
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`:

```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.