Most MariaDB operators have never deliberately created an Aria table, and many could not tell you what engine it is. Yet if you run MariaDB 10.4 or later, Aria holds your privilege tables, your time zone tables, and every internal temporary table that spills to disk during a big GROUP BY. It is one of those components that is invisible right up until the day it is not — the day a crash leaves aria_log files replaying on startup, or a temp-heavy workload runs slow because the Aria page cache is still at its small default while the InnoDB buffer pool got all the attention.
This is the operator's tour of Aria: what it actually is, where MariaDB uses it whether you asked or not, how it really compares to InnoDB, and the handful of knobs worth knowing.
What Aria is
Aria is MariaDB's crash-safe successor to MyISAM, originally developed under the name Maria — which is where the "Maria" in MariaDB comes from. MyISAM's fatal flaw was never performance for its niche; it was that any unclean shutdown could leave tables corrupted, followed by the REPAIR TABLE lottery and the occasional unrecoverable .MYI file. Aria's design goal was to keep MyISAM's simplicity and low overhead while making crashes survivable.
It achieves that with the same fundamental machinery every crash-safe engine uses: a redo log and a cache of data pages. Aria's default row format, PAGE, writes changes to a log (the aria_log.00000001 files you may have noticed in the datadir) and caches table pages in its own page cache, sized by aria_pagecache_buffer_size. After an unclean shutdown, recovery replays the log at startup and the tables come back consistent — no REPAIR TABLE, no prayer. The alternative row formats, FIXED and DYNAMIC, are the old MyISAM-style unlogged formats and exist mostly for compatibility; if you create an Aria table yourself, PAGE is the only format worth choosing, and it is the default.
Where MariaDB uses Aria whether you asked or not
Two places, and both matter operationally. First, since MariaDB 10.4, the mysql system database's grant tables — global_priv, db, tables_priv, proxies_priv, and friends — are stored in Aria rather than MyISAM. One wrinkle to know before you check: mysql.user, the table everyone actually queries, is since 10.4 a compatibility view over the real mysql.global_priv table, so it reports no engine of its own. This is a quiet but real reliability improvement: a crashed server no longer risks corrupting its own grant tables, which used to be one of the more embarrassing ways to extend an outage. Second, internal temporary tables. When a query needs a temporary table that exceeds tmp_table_size or max_heap_table_size, MariaDB converts it to an on-disk table, and the on-disk engine is Aria (controlled by aria_used_for_temp_tables, on by default since 10.1). Every oversized GROUP BY, every big derived table, every filesort-adjacent temp table that spills, lands in Aria.
-- Which engine are your system tables on? (MariaDB 10.4+: Aria; mysql.user is a view and shows no engine)
SELECT table_name, engine
FROM information_schema.tables
WHERE table_schema = 'mysql'
ORDER BY table_name;
-- Is your workload spilling temp tables to disk?
SHOW GLOBAL STATUS LIKE 'Created_tmp_tables';
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';
-- The threshold that decides when spill happens:
SHOW GLOBAL VARIABLES LIKE 'tmp_table_size';
SHOW GLOBAL VARIABLES LIKE 'max_heap_table_size';
The effective spill threshold is the smaller of tmp_table_size and max_heap_table_size, which trips people up constantly: raising only one of them does nothing. When Created_tmp_disk_tables climbs as a fraction of Created_tmp_tables, either your queries are materializing more than they should or the thresholds are set for a world you no longer live in.
Aria vs InnoDB: the honest comparison
This is not a fair fight, and it is not supposed to be. InnoDB is a fully transactional engine: MVCC, row-level locking, foreign keys, multi-statement transactions with rollback, a buffer pool that doubles as a write cache, and decades of production hardening under write-heavy concurrency. Aria is none of those things. It is not transactional — there is no COMMIT/ROLLBACK semantics across statements, no MVCC, no consistent reads, no foreign keys. Locking is at the table level rather than the row level — the same granularity as MyISAM — so there is nothing like InnoDB's row-level concurrency under mixed read/write load. Aria's real gains over its predecessor are crash safety and proper page caching, not finer locks.
Where Aria genuinely wins is overhead. For read-mostly or bulk-load workloads, an Aria table is often smaller on disk and cheaper to scan than the same data in InnoDB, because it carries no undo, no transaction metadata per row, and a much lighter page structure — though the margin depends on row format, indexes, and the shape of the scan, so measure it rather than assume it. Bulk inserts into an empty Aria table are fast and simple. For internal temp tables — write once, read once, discard — that profile is exactly right, which is why MariaDB chose it: you do not want InnoDB's transactional machinery, redo, and doublewrite tax on a table that lives for the duration of one query.
The practical guidance has not changed in years and I see no reason to get creative about it: use InnoDB for every table that belongs to your application, and let Aria do the jobs MariaDB assigned to it. If you are tempted to use Aria for a user-facing logging or archive table because "it is mostly reads," do the honest math on what a crash mid-insert costs you — Aria's crash safety covers the table structure and logged pages, but without transactions there is no notion of a partially applied batch to roll back. InnoDB's overhead is the price of never having that conversation.
The knobs worth knowing
Aria's page cache defaults to 128 MB via aria_pagecache_buffer_size. For the mysql system tables that is beyond generous — they are tiny. The knob earns its attention when your workload spills large temp tables: those reads and writes go through the Aria page cache, and a temp-heavy analytical workload on a 128 MB cache will thrash. If your monitoring shows heavy Created_tmp_disk_tables with slow queries to match, raising the page cache is cheap memory well spent. The companion status variables Aria_pagecache_reads and Aria_pagecache_read_requests give you the hit behavior, same as InnoDB's buffer pool counters.
Recovery is the other knob-adjacent topic. After a crash, startup replays the Aria log before the server accepts connections; you will see it in the error log. On a busy temp workload the log is usually small and replay takes seconds. If you ever see Aria recovery take minutes, that is a signal the page cache was very dirty or the log had grown large — worth investigating, not ignoring. And should you ever need it, the aria_chk utility can check and repair Aria tables offline, the spiritual successor to myisamchk; CHECK TABLE and REPAIR TABLE also work online. In a decade of running MariaDB I have needed aria_chk for system tables exactly zero times, which is the entire point of the engine.
One more operational footnote: because internal temp tables use Aria, tmpdir matters. Temp files land in tmpdir, and if that directory sits on a small root partition or a tmpfs that the host also uses for other things, a runaway temp table can fill it and take the query — or worse, the host — down with it. Point tmpdir somewhere with room, on storage that does not mind the write churn.
Watching the engine nobody watches
Aria's counters are a paragraph in SHOW GLOBAL STATUS, and that is why they get ignored: Aria_pagecache_reads, Aria_pagecache_read_requests, the temp table counters, and the recovery lines in the error log. Trend the temp spill ratio and the page cache behavior together and you will catch the "queries got slow after the reporting rollout" class of incident before the postmortem stage.
If you take one thing from this post, trend Created_tmp_disk_tables against Created_tmp_tables starting tonight — that ratio is the earliest warning Aria ever gives you. MonPG, the tool I work on, monitors PostgreSQL today; MariaDB support is being built now, and the coming-soon page tracks it. Temp-spill attribution and per-engine cache hit behavior are exactly the signals it is being designed around, because they are the signals that stay invisible until they are expensive. Until the MariaDB side ships, the status variables above carry the load. If PostgreSQL is also part of your fleet — where the analog is work_mem spills and temp file bytes in pg_stat_database — the workflow exists today; see the PostgreSQL overview, the engine comparison, and more field notes on the blog.