MariaDB Catalogs preview containers available

We’ve made significant progress on MariaDB Catalogs, and while there’s still work to be done, we’re excited to offer the community an easy way to try out our preview release. You no longer need to compile the source code yourself—just use our prebuilt containers, now available on our official quay.io development registry.

The code is available publicly on Github, in a separate repo compared to the official MariaDB Server (until the feature gets published as part of an official MariaDB Server release)

Documentation is available on the Knowledge Base. For a step-by-step guide on catalogs, read on!

🚀 How to Download

docker pull quay.io/mariadb-foundation/mariadb-devel:mariadb-catalogs-preview

This image is based on Ubuntu 24.04 and includes manually installed MariaDB packages. Please note that no repository is configured for updates—this is strictly a preview release.

The underlying MariaDB version is still 11.0, so features introduced in newer versions may be missing.

🛠️ How to Get Started

This image builds on our official Docker images on Docker Hub, with one added initialization variable: MARIADB_CATALOGS, which expects a comma separated list of catalog names (no spaces).

To run the image, mount a volume for the data directory and initialize your desired catalogs:

docker run                          \
    -v ./datadir:/var/lib/mysql     \
    -e MARIADB_CATALOGS=cat1,cat2   \
    -e MARIADB_ROOT_PASSWORD=1234   \
    --name mariadb-with-catalogs    \
    --rm                            \
    -it quay.io/mariadb-foundation/mariadb-devel:mariadb-catalogs-preview


Once initialized, your data directory structure will look like this:

$ sudo tree -d
.
├── #rocksdb
├── cat1
│   ├── mysql
│   ├── performance_schema
│   └── sys
├── cat2
│   ├── mysql
│   ├── performance_schema
│   └── sys
└── def
    ├── mysql
    ├── performance_schema
    └── sys

Each catalog (e.g., cat1, cat2) gets its own mysql, performance_schema, and sys databases.

🔌 How to Connect

With this setup, all the default initialization parameters available via our traditional Dockerhub images will work on the def catalog. That means that the traditional root user with password 1234 (as in the example command above) will reside in the def catalog.

The simplest way to connect is via the mariadb client, already installed in the container. This will facilitate administrative operations.

docker exec -it mariadb-with-catalogs mariadb -u root --password=1234

You will be greeted with a prompt of the form:

MariaDB [def.(none)]>

You are now connected to the def catalog, which is the catalog containing all the catalogs metadata. Users created here will not be visible in other catalogs.

We can list all available catalogs with:

MariaDB [def.(none)]> show catalogs;
+---------+-----------------+
| Catalog | Comment         |
+---------+-----------------+
| cat1    |                 |
| cat2    |                 |
| def     | default catalog |
+---------+-----------------+

Newer clients (as the ones present in the container) support a specific catalog flag. We can use it to connect to a separate catalog as its root user:

docker exec -it mariadb-with-catalogs mariadb --catalog cat1 -u root

With older clients, we can use the database name to specify the catalog:

docker exec -it mariadb-with-catalogs mariadb -u root cat1.mysql

The root user in the def catalog has special privileges compared to other catalogs’ root users. It is able to change catalogs and do operations within each catalog.

MariaDB [def.(none)]> use catalog cat1;
Query OK, 0 rows affected (0.000 sec)

MariaDB [cat1.(none)]> create user foo;
Query OK, 0 rows affected (0.020 sec)

MariaDB [cat1.(none)]> select user, host from mysql.user;
+-------------+-----------+
| User        | Host      |
+-------------+-----------+
| foo         | %         |
| root        | 127.0.0.1 |
| root        | ::1       |
| mariadb.sys | localhost |
| root        | localhost |
+-------------+-----------+
5 rows in set (0.001 sec)

💾 Tables and Storage Engines

This preview supports multiple storage engines, all supporting catalogs, including:

  • RocksDB
  • InnoDB
  • Connect
  • MyISAM
  • Aria
# Within a catalog, you can run:
CREATE DATABASE test_db;
USE test_db;

CREATE TABLE t1 (a INT) ENGINE=InnoDB;
CREATE TABLE t2 (a INT) ENGINE=RocksDB;

SHOW TABLES;

🧑‍💼 Managing Catalogs

Catalogs are primarily meant for SaaS providers to easily create multi-tenant systems. That means the MariaDB Server should support the SQL commands to properly automate this.

First, initial deployment is handled via the mariadb-install-db script. This script will create all the catalogs passed in through the command line argument --catalogs=cat1,cat2,cat3. This is what the container image also does behind the scenes with the MARIADB_CATALOGS environment variable.

Subsequently, we have to be able to create more catalogs, as more tenants get enrolled into the system. This is done via the [CREATE | DROP] CATALOG command. Let’s have a look:

MariaDB [def.(none)]> create catalog cat3;
Query OK, 1 row affected (0.380 sec)

MariaDB [cat1.(none)]> use catalog cat3;
Query OK, 0 rows affected (0.000 sec)

MariaDB [cat3.(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.000 sec)

You’ll notice that creating the catalog takes a bit more time than the other commands. That is because it’s effectively “bootstrapping” a new server schema. The difference is that there are no users created for this catalog by default. So the sysadmin now needs to also create users for cat3;

MariaDB [cat3.(none)]> select user, host from mysql.user;
+-------------+-----------+
| User        | Host      |
+-------------+-----------+
| mariadb.sys | localhost |
+-------------+-----------+
1 row in set (0.000 sec)

And just the same, we can drop the newly added catalog:

MariaDB [cat3.(none)]> drop catalog cat3;
ERROR 4201 (HY000): Current catalog 'cat3' cannot be dropped
MariaDB [cat3.(none)]> use catalog cat2;
Query OK, 0 rows affected (0.000 sec)

MariaDB [cat2.(none)]> drop catalog cat3;
Query OK, 0 rows affected (0.241 sec)

Notice that we were not able to drop the catalog as long as we had users connected to it.

📈 Status Variables

One important aspect of catalogs is monitoring the server status. In MariaDB there are already global and session level variables, however with the introduction of another hierarchy level (catalogs), global now actually refers to the current catalog status. For server wide variables, there is now a “server” level variable and global is now a synonym for “catalog” level. This preserves backwards compatibility of applications.

Not all status variables are yet supported, but we can test out a few, for example Acl_users. We’ll connect to two different catalogs and check the value:

MariaDB [cat1.(none)]> show global status like 'Acl_users';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Acl_users     | 5     |
+---------------+-------+
1 row in set (0.000 sec)

MariaDB [cat1.(none)]> select count(*) from mysql.user;
+----------+
| count(*) |
+----------+
|        5 |
+----------+
1 row in set (0.001 sec)

And now if we try the same for cat2, on which we’ve created an extra user previously:

MariaDB [cat2.(none)]> select count(*) from mysql.user;
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (0.000 sec)

MariaDB [cat2.(none)]> show global status like 'Acl_users';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Acl_users     | 6     |
+---------------+-------+
1 row in set (0.000 sec)

Remember, that this is still work in progress code, so there may be edge cases we do not yet handle properly here.

Documentation

While this post has highlighted the majority of functionality available in MariaDB Catalogs, the full documentation is available on the MariaDB KnowledgeBase.

On a final note

Catalogs is a big project, that involved quite some development effort. This project would not have been possible without the support of our sponsors, such as IONOS and through structural funding via NlNet. We encourage the community to contribute with testing, bug reports and potential PRs to the public repository on Github