MariaDB data freshness check and alerts
Connect MariaDB to arcodash with a host, a read-only user and a database name, then schedule SQL that returns one number and alert when it crosses a threshold. arcodash talks to MariaDB over the MySQL protocol, so the connection form is the same as MySQL's. The differences that matter are in the server: no ONLY_FULL_GROUP_BY by default, max_statement_time instead of max_execution_time, and JSON columns that are really text.
Connect MariaDB
The form takes host, port (3306 by default), user, password and db, the same as MySQL, because arcodash uses one MySQL-wire client for both. There is no SSL setting on the form and no SSH tunnel. arcodash refuses hosts that resolve to private or loopback addresses and publishes no fixed outbound IPs, so the server needs a public endpoint your firewall can admit. A wrong host fails after 5 seconds. See Connectors overview for testing a connection and schema introspection.
Create a user that can only select:
CREATE USER 'arcodash_ro'@'%' IDENTIFIED BY 'a-long-random-password';
GRANT SELECT ON shop.* TO 'arcodash_ro'@'%';
Grant per schema. If the data lives on a replica, the freshness numbers describe the replica, which matters when it lags.
Where MariaDB differs
Three differences show up in monitoring, and they are server behavior, not arcodash behavior.
Statement timeouts. MariaDB’s variable is max_statement_time, in seconds and fractional, default 0 meaning no limit, settable globally or per session. On MySQL and TiDB the equivalent is max_execution_time in milliseconds. arcodash tries to set max_execution_time when it connects and ignores the failure, so on MariaDB that DB-side backstop is simply absent; the 300 second cap in arcodash is what stops a slow run. If you want a tighter limit for one expensive check, MariaDB has a per-statement form:
SET STATEMENT max_statement_time=30 FOR
SELECT COUNT(*) AS rows_last_24h
FROM events
WHERE loaded_at >= UTC_TIMESTAMP() - INTERVAL 24 HOUR;
The SET STATEMENT ... FOR prefix is MariaDB only, so it is a syntax error on MySQL.
sql_mode. The documented default is STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION (system variables). ONLY_FULL_GROUP_BY is absent, so SELECT d, amount ... GROUP BY d runs and returns an arbitrary amount. That is a quiet way to chart a wrong number. Write every grouped query as if the mode were on.
JSON. JSON in MariaDB is an alias for LONGTEXT COLLATE utf8mb4_bin with a JSON_VALID check, and values compare as plain strings (JSON data type). arcodash shows such a column as text. Use JSON_VALUE(payload, '$.status') in the query to chart a field out of it.
A freshness check
A check is a scheduled query that returns one row with one numeric column. The monitor reads that first row and compares the column with your threshold.
SELECT COALESCE(
TIMESTAMPDIFF(MINUTE, MAX(loaded_at), UTC_TIMESTAMP()),
999999
) AS minutes_since_last_row
FROM events;
Alert when minutes_since_last_row is > 120. The COALESCE matters: on an empty table MAX() is NULL, and a NULL never crosses a threshold. UTC_TIMESTAMP() fits a DATETIME that your loader writes in UTC; use NOW() against a TIMESTAMP. The data observability monitors guide explains why a check must return exactly one row.
A volume check and a metric alert
Volume, rows in the last day:
SELECT COUNT(*) AS rows_last_24h
FROM events
WHERE loaded_at >= UTC_TIMESTAMP() - INTERVAL 24 HOUR;
Alert with < and a floor well under a normal day, or use a baseline monitor that learns the usual count. Validity, the share of orders with no customer:
SELECT 100.0 * SUM(customer_id IS NULL) / NULLIF(COUNT(*), 0) AS orphan_pct
FROM orders
WHERE created_at >= UTC_TIMESTAMP() - INTERVAL 1 DAY;
Alert when orphan_pct is > 1. Index created_at and loaded_at, or every run scans the table.
History tables and replica lag
MariaDB supports system-versioned tables, where the server keeps every old row version and you query the past with FOR SYSTEM_TIME (temporal data tables). If your tables use it, a dashboard can chart how a value changed without a separate audit table. Check the docs page for the exact syntax on your server version before relying on it.
For a replica, run SHOW REPLICA STATUS (older servers: SHOW SLAVE STATUS) when a freshness alert fires and the primary looks fine. A lagging replica looks exactly like a stalled pipeline.
Dashboard tiles
A MariaDB dashboard is plain SQL, the same as on any database. Three that earn their space:
SELECT DATE(created_at) AS day, COUNT(*) AS orders
FROM orders
GROUP BY DATE(created_at)
ORDER BY day;
SELECT status, COUNT(*) AS n
FROM orders
WHERE created_at >= UTC_TIMESTAMP() - INTERVAL 7 DAY
GROUP BY status;
SELECT JSON_VALUE(payload, '$.plan') AS plan, COUNT(*) AS signups
FROM events
WHERE loaded_at >= UTC_TIMESTAMP() - INTERVAL 30 DAY
GROUP BY JSON_VALUE(payload, '$.plan');
The last one repeats the expression in GROUP BY rather than the alias, which is the form that also works on stricter servers. Runs keep at most 10,000 rows, so aggregate in SQL (Limits). arcodash is hosted only; the trial is 14 days free and then from $59 a month with unlimited seats.
The MySQL connector page has the shared query patterns.
docsMariaDB setup in the docs
Connection fields, an example configuration and caveats.
Questions
Is MariaDB a separate connector in arcodash?
It is its own entry in the connector list, but under the hood it uses the same MySQL-protocol client as the MySQL and TiDB entries. The connection fields are identical. Choosing MariaDB just labels the connection correctly.
Why did my MariaDB query pass here but fail on a MySQL server?
MariaDB's default sql_mode does not include ONLY_FULL_GROUP_BY, so a query that selects an ungrouped column runs on MariaDB and is rejected by MySQL 8.4. Aggregate the column or use ANY_VALUE() so the query means the same on both.
How do I stop a runaway check query on MariaDB?
Set max_statement_time globally or for the session, or prefix a single statement with SET STATEMENT max_statement_time=30 FOR. arcodash itself stops every run after 300 seconds regardless.