MariaDB: The usage of MARIADB_AUTO_UPGRADE

MariaDB: The usage of MARIADB_AUTO_UPGRADE

When you're running MariaDB and keep it up to date, binaries are updated (either because of updates running within OS update, or by updating Docker containers), and you won't have to do anything - it just works.

In MySQL, this isn't a problem; the database dictionary as well as internal objects were just upgraded implicitly when starting the database with ne newest binaries.

In Oracle, it can be a problem: when you apply patches ("release updates"), which are something like a minor release update, you'll have to execute datapatch, which updates internal database objects to the latest version. If you forget to do it, you might never get an error - but your database is not in the best state.

So what about MariaDB?

When you have a look into MariDB log files, you might see something like this:

MariaDB upgrade (mariadb-upgrade or creating healthcheck users) required, but skipped due to $MARIADB_AUTO_UPGRADE setting

In my case, my docker-compose.yml looks like this:

services:
  db:
    image: mariadb
    hostname: mariadb
    ports:
      - 13306:3306
    environment:
      - MARIADB_ROOT_PASSWORD=XxXxXxXx

The logfile already gives us a hint what to do:

MariaDB upgrade required, but skipped due to $MARIADB_AUTO_UPGRADE setting

So let's just add this parameter to my YAML file:

services:
  db:
    image: mariadb
    hostname: mariadb
    ports:
      - 13306:3306
    environment:
      - MARIADB_ROOT_PASSWORD=XxXxXxXx
      - MARIADB_AUTO_UPGRADE=true

Now, let's restart the container:

# docker compose up -d

And have look at the log files:

# docker compose logs -f
db-1  | 2025-06-13 09:48:01+00:00 [Note] [Entrypoint]: Backing up system database to system_mysql_backup_11.7.2-MariaDB.sql.zst
db-1  | 2025-06-13 09:48:01+00:00 [Note] [Entrypoint]: Backing up complete
db-1  | 2025-06-13 09:48:01+00:00 [Note] [Entrypoint]: Starting mariadb-upgrade
db-1  | The --upgrade-system-tables option was used, user tables won't be touched.
db-1  | Major version upgrade detected from 11.7.2-MariaDB to 11.8.2-MariaDB. Check required!
db-1  | Phase 1/8: Checking and upgrading mysql database
db-1  | Processing databases
db-1  | mysql
db-1  | mysql.column_stats                                 OK
db-1  | mysql.columns_priv                                 OK
db-1  | mysql.db                                           OK
db-1  | mysql.event                                        OK
db-1  | mysql.func                                         OK
db-1  | mysql.global_priv                                  OK
db-1  | mysql.gtid_slave_pos                               OK
db-1  | mysql.help_category                                OK
db-1  | mysql.help_keyword                                 OK
db-1  | mysql.help_relation                                OK
db-1  | mysql.help_topic                                   OK
db-1  | mysql.index_stats                                  OK
db-1  | mysql.innodb_index_stats                           OK
db-1  | mysql.innodb_table_stats                           OK
db-1  | mysql.plugin                                       OK
db-1  | mysql.proc                                         OK
db-1  | mysql.procs_priv                                   OK
db-1  | mysql.proxies_priv                                 OK
db-1  | mysql.roles_mapping                                OK
db-1  | mysql.servers                                      OK
db-1  | mysql.table_stats                                  OK
db-1  | mysql.tables_priv                                  OK
db-1  | mysql.time_zone                                    OK
db-1  | mysql.time_zone_leap_second                        OK
db-1  | mysql.time_zone_name                               OK
db-1  | mysql.time_zone_transition                         OK
db-1  | mysql.time_zone_transition_type                    OK
db-1  | mysql.transaction_registry                         OK
db-1  | Phase 2/8: Installing used storage engines... Skipped
db-1  | Phase 3/8: Running 'mysql_fix_privilege_tables'
db-1  | Phase 4/8: Fixing views... Skipped
db-1  | Phase 5/8: Fixing table and database names ... Skipped
db-1  | Phase 6/8: Checking and upgrading tables... Skipped
db-1  | Phase 7/8: uninstalling plugins
db-1  | Phase 8/8: Running 'FLUSH PRIVILEGES'
db-1  | OK
db-1  | 2025-06-13 09:48:18+00:00 [Note] [Entrypoint]: Finished mariadb-upgrade
db-1  | 2025-06-13 09:48:18+00:00 [Note] [Entrypoint]: Stopping temporary server
db-1  | 2025-06-13  9:48:18 0 [Note] mariadbd (initiated by: unknown): Normal shutdown
db-1  | 2025-06-13  9:48:18 0 [Note] InnoDB: FTS optimize thread exiting.
db-1  | 2025-06-13  9:48:18 0 [Note] InnoDB: Starting shutdown...
db-1  | 2025-06-13  9:48:19 0 [Note] InnoDB: Removed temporary tablespace data file: "./ibtmp1"
db-1  | 2025-06-13  9:48:19 0 [Note] InnoDB: Shutdown completed; log sequence number 47629; transaction id 18
db-1  | 2025-06-13  9:48:19 0 [Note] mariadbd: Shutdown complete
db-1  | 2025-06-13 09:48:19+00:00 [Note] [Entrypoint]: Temporary server stopped
db-1  | 2025-06-13  9:48:19 0 [Note] Starting MariaDB 11.8.2-MariaDB-ubu2404 source revision 8d36cafe4fc700e6e577d5a36650c58707e76b92 server_uid i/adQyORMBjdCbV+zs20lFGiMUA= as process 1
[...]

So what does MARIADB_AUTO_UPGRADE mean? Let's have a look at the MariaDB documentation:

Set MARIADB_AUTO_UPGRADE to a non-empty value to have the entrypoint check whether mariadb-upgrade needs to run, and if so, run the upgrade before starting the MariaDB server.

Ok, without setting MARIADB_AUTO_UPGRADE, there will be no check and no upgrade.

Before the upgrade, a backup of the system database is created in the top of the datadir with the name system_mysql_backup_*.sql.zst. This backup process can be disabled with by setting MARIADB_DISABLE_UPGRADE_BACKUP to a non-empty value.

So, when enabling MARIADB_AUTO_UPGRADE, a backup of the dictionary will be made.

If MARIADB_AUTO_UPGRADE is set, and the .my-healthcheck.cnf file is missing, the healthcheck users are recreated if they don't exist, MARIADB_HEALTHCHECK_GRANTS
grants are given, the passwords of the healthcheck users are reset to a random value and the .my-healthcheck.cnf file is recreated with the new password populated.

Great: healthcheck users are created automatically if they do not exist.

At this point, I'd rather keep MARIADB_HEALTHCHECK_GRANTS set as long as I never intend to go back to an older version (say: downgrade). But this needs a development or test system, which I always recommend to have for a production system. Or, if your MariaDB server is only production, there should be other possibilities to roll back to an older state - like filesystem snapshots.

Let me say it in short words: always test each update. And always have backups. And if you have, use non-production systems to test updates there. Then, automatic updates are completely fine 😄