Free MySQL hosting: start on MariaDB, upgrade to MySQL when you need it
MySQL is not on the Layerbase free tier. It starts on the Solo plan at $5/mo, and the reason is memory: a MySQL 9.x server idles at roughly half a gigabyte before you have inserted a row, and the ProxySQL sidecar in front of it adds about 60 MB on top. A free database is budgeted 256 MB. MariaDB idles at around 135 MB, fits inside that, and speaks the MySQL wire protocol, so it is what you get when you want MySQL hosting for nothing.
That trade is smaller than it sounds. mysql2, Prisma, Drizzle, PDO, and the mysql command line client all connect to MariaDB without a code change, and a mysqldump file from MySQL 8 restores into a current MariaDB with far fewer edits than most advice online assumes. What still breaks is a short list: DEFINER clauses on views, triggers and routines; users and grants that were never in the file to begin with; utf8mb3 columns that import cleanly and cost you four-byte characters later; and two mysqldump flags that most people only find out about by reading an error.
This post is the whole route. Why the free engine is MariaDB, what a free database actually gives you, the dump command that survives a restricted source account, each restore error and what it means, the MySQL features that do not travel, and what to do the day you want real MySQL back.
If you want the procedure rather than the error reference, moving a MySQL database off cPanel shared hosting is the step-by-step version. Everything below applies to any MySQL source: a shared host, a droplet you are decommissioning, RDS, PlanetScale, a laptop.
What a free MariaDB database gives you
Two databases and 5 GB of storage, up to 20 concurrent connections, one instant branch per database, one manual backup slot, and no credit card. That is the whole Free plan, and MariaDB is one of the engines on it.
The part worth planning around is sleep. A free MariaDB hibernates after 30 minutes with no connections and wakes on connect: the first connection is held open while the engine starts. The cold start runs about 20 seconds, which is longer than some client connect timeouts (mysql2 defaults to 10 seconds), so give your client a 30 second connect timeout or expect the first attempt to fail and retry. You can also start the database from its page before you connect. If it has to stay awake for a live site, that is a paid feature: the Solo plan at $5/mo gives you a 768 MB always-on pool you pin one database to so it never sleeps.
Two ways to get the data across
If the source database is still reachable over the network, skip the file entirely. Pick Migrating from another platform at cloud.layerbase.com/create, choose MySQL as the source type, paste a mysql:// connection string, and set the target engine to MariaDB. We run the dump and load once against a source we never write to.
One thing to get right there: choose MySQL as the source type even though you are landing on MariaDB. A MySQL 8 server still on its default caching_sha2_password authentication cannot be read by MariaDB's dump tools, so the MariaDB source path is for MariaDB sources only.
If the source is on a laptop, behind a VPN, or already sitting in a .sql file, do it by hand. The rest of this post is that path.
The collation error, and why you probably will not hit it
The single most repeated piece of MySQL-to-MariaDB advice is that your dump will die on this:
ERROR 1273 (HY000) at line 24: Unknown collation: 'utf8mb4_0900_ai_ci'MySQL 8 made utf8mb4_0900_ai_ci the default collation, MariaDB implemented Unicode 14 collations under a uca1400 name instead, and for several years the two did not know about each other. Every dump from a default MySQL 8 install carries the collation name in each CREATE TABLE, so the restore stopped at the first table.
That was fixed. MDEV-35256 aliases MySQL's language-neutral 0900 collations onto the MariaDB 1400 equivalents, closed as fixed with a stated fix version of 11.4.5 (checked 2026-08-26). MariaDB's own collation reference now lists utf8mb4_0900_ai_ci with the description "Alias for utf8mb4_uca1400_nopad_ai_ci".
So the error is a version question, not a compatibility question. On 11.4.5 or newer, the dump restores. On an older series it fails exactly as advertised, and 10.11 is the LTS most people still land on when they pick "the stable one" from a version dropdown. On Layerbase the default for a new MariaDB database is 11.8, and 10.11 is still offered, so this is a real choice you make at create time rather than something the platform decides for you.
If you are stuck on an older server and cannot move, the fix is a search and replace over the dump before you load it:
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_general_ci/g' dump.sqlThat is a sort-order change, not a rename. utf8mb4_general_ci orders differently from a UCA 14 collation, which matters if you rely on ORDER BY for anything a human reads. Prefer the newer server.
DEFINER: error 1227
This one has not gone anywhere:
ERROR 1227 (42000) at line 812: Access denied; you need (at least one of) the SUPER privilege(s) for this operationMySQL's server error reference gives 1227 as ER_SPECIFIC_ACCESS_DENIED_ERROR, SQLSTATE 42000, message "Access denied; you need (at least one of) the %s privilege(s) for this operation" (checked 2026-08-26). In a restore it almost always means one thing: your dump contains an object stamped with the account that created it on the old server.
/*!50017 DEFINER=`olduser`@`localhost` */mysqldump writes that stamp onto views, triggers, stored procedures, functions and events. Creating an object owned by an account that is not you needs elevated privilege, and on any managed database you are not the superuser. On a shared host the definer is usually something like cpaneluser_wp@localhost, an account that does not exist anywhere else in the world.
Strip it on the way in:
sed -E 's/DEFINER=`[^`]+`@`[^`]+`//g' dump.sql > dump-clean.sqlThe objects then get created owned by whoever runs the restore, which is what you wanted. There is no --skip-definer on mysqldump to save you the step; the option existed on mysqlpump, which Oracle deprecated. Check what is actually affected before you assume it is nothing:
SELECT TABLE_SCHEMA, TABLE_NAME, DEFINER FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = 'yourdb';
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, DEFINER FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'yourdb';
SELECT TRIGGER_SCHEMA, TRIGGER_NAME, DEFINER FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'yourdb';Empty results on all three and you can skip the sed entirely. Most small application databases come back empty, which is why plenty of people move without ever meeting error 1227.
While you are here: --triggers is on by default, and stored routines and events are not. If the three queries above return rows, your dump command needs --routines --events or those objects silently do not travel. That failure has no error message at all, which makes it worse than 1227.
Users and grants were never in the file
A database dump contains schemas and data. It does not contain accounts. MySQL's documentation is direct about this: mysqldump does not export user accounts or grants, because those live in the mysql system schema, which you dump separately and should not restore onto a different server.
On shared hosting this bites harder than it sounds, because cPanel-style panels create a user per application with a prefixed name, and applications hold that name in config files. After the move you get one account from the managed provider with a generated password. Anything in your codebase that references the old username changes.
Take an inventory before you tear the old server down:
SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'olduser'@'localhost';You are reading it to find out what your application actually needed, not to replay it. A managed database hands you a single account with rights over your own schema, so the interesting question is whether anything was relying on a second account with narrower rights, and almost nothing is.
utf8mb3 imports fine, which is the problem
Nothing errors here. That is what makes it worth a section.
Databases created on MySQL 5.x default to the character set the server was configured with, and on a lot of older shared hosting that is utf8, which is not what it sounds like. MySQL's manual is unambiguous: utf8mb3 is deprecated, "remains supported for the lifetimes of the MySQL 8.0.x and MySQL 8.4.x LTS release series", and the guidance is that "all new applications should use utf8mb4" (checked 2026-08-26 from the utf8mb3 reference page).
utf8mb3 stores at most three bytes per character, which covers the Basic Multilingual Plane and excludes emoji, many CJK extension characters, and a pile of symbols people paste into text fields. A table declared utf8 on the old host arrives on the new one still declared utf8mb3, still working, still unable to store a rocket emoji. You find out when a user submits one and the write fails or the string truncates at the emoji.
Find out where you stand before the move, not after:
SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'yourdb' AND CHARACTER_SET_NAME IS NOT NULL
AND CHARACTER_SET_NAME <> 'utf8mb4';The conversion is per table:
ALTER TABLE posts CONVERT TO CHARACTER SET utf8mb4;Do it on the new server, after the restore, one table at a time, with a backup you can go back to. Converting rewrites the table and widens every character column's storage, which is a real consideration on any index built over a long VARCHAR: a 255-character column goes from 765 bytes of index key to 1020. On modern InnoDB row formats there is room for that. On an ancient one there is not, and the ALTER tells you so rather than corrupting anything.
If the old database is genuinely ASCII-only, converting still costs you nothing and closes the question permanently.
The two flags you learn about from an error
Both of these fire on the dump side, before you have gone anywhere, and both are confusing because the error names something you never asked for.
mysqldump: Couldn't execute 'SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, ...)':
Unknown table 'COLUMN_STATISTICS' in information_schema (1109)MySQL 8's mysqldump asks the server for column histogram statistics by default. Servers that do not have that table, which includes MariaDB and MySQL 5.7, answer with 1109. It is not a corruption signal and it does not mean your data is unreadable. Add --column-statistics=0 and it goes away.
mysqldump: Error: 'Access denied; you need (at least one of) the PROCESS privilege(s)
for this operation' when trying to dump tablespacesThis is error 1227 again, wearing a different hat. mysqldump asks the server about tablespaces, that question needs the PROCESS privilege, and a shared-hosting account does not have it. --no-tablespaces suppresses the CREATE TABLESPACE and CREATE LOGFILE GROUP statements you were never going to use.
Put together, the dump command that survives contact with a restricted source account looks like this:
mysqldump \
--single-transaction \
--no-tablespaces \
--column-statistics=0 \
--routines --events \
--default-character-set=utf8mb4 \
-h HOST -u USER -p DBNAME > dump.sql--single-transaction is the one worth understanding rather than copying. It takes a consistent snapshot without locking, which works because InnoDB is transactional. It does nothing for MyISAM tables, which a fifteen-year-old shared-hosting database often still has. Check first:
SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'yourdb' AND ENGINE <> 'InnoDB';Rows in that result mean your snapshot is not consistent for those tables and you should stop writes during the dump, or convert them to InnoDB first and then dump.
Checking the restore actually landed
Row counts are the check people run and the weakest one, because a truncated dump that stopped at table 40 of 60 gives you perfect row counts for the first 39.
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'yourdb';
SELECT COUNT(*) FROM information_schema.VIEWS WHERE TABLE_SCHEMA = 'yourdb';
SELECT COUNT(*) FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = 'yourdb';
SELECT COUNT(*) FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'yourdb';Run those four on both sides and compare the numbers. Views and routines are where a DEFINER failure or a missing --routines shows up, and neither of them affects a single row count.
Then take the largest three tables and compare COUNT(*) and MAX(id), and run SHOW CREATE TABLE on both servers for one table with an interesting schema. Character set and collation are printed there, so it doubles as your utf8mb3 check.
What you actually give up
Your driver does not change and your CRUD does not change, so the differences show up in narrow places.
The one that has bitten real applications is multi-valued indexes on JSON arrays. MySQL can index the individual elements of a JSON array so a lookup into it does not scan the table; MariaDB has no equivalent, so at scale you either normalize those arrays into a proper table or accept the scan. If your schema leans on that, MariaDB is not a free substitute, it is a slower one.
The second is authentication plugins. MySQL 8 defaults to caching_sha2_password, and anything that names an auth plugin explicitly (a CREATE USER you replay, a client config, a driver flag) needs revisiting rather than copying. This is the same fact that makes MariaDB's dump tools unable to read a default MySQL 8 server, which is why the import wizard asks you to pick MySQL as the source type.
The traffic goes the other way too. MariaDB has sequences and system-versioned tables, and neither has a MySQL equivalent worth the name: CREATE SEQUENCE replaces a locked counter table, and ALTER TABLE ... ADD SYSTEM VERSIONING replaces an audit table plus triggers. MySQL vs MariaDB is the full accounting in both directions, with runnable examples.
Going the other way, later
The Convert tab in the dashboard runs both directions now. MariaDB to MySQL is one click from the database page on Solo and above: Layerbase creates a new MySQL database next to the MariaDB one, copies the schema and data into it, and leaves the original untouched until you archive it yourself. You can keep your address, so the host, port and password your application already has move onto the MySQL database at the handover and nothing gets redeployed.
The pre-check is the part worth reading. When it can reach your database it runs before anything is created and reports the MariaDB-only features it knows to look for: MariaDB-only column types (UUID, INET4, INET6, VECTOR) and CREATE SEQUENCE objects. Nothing rewrites those for you, so each stops the restore on the statement that names it. Fix them on the MariaDB side first and the copy is uneventful. Collations are the one it handles itself. MariaDB 11.8 defaults a new database to utf8mb4_uca1400_ai_ci, so nearly every table declares one, and the conversion rewrites them onto MySQL's utf8mb4_0900 family as it copies: _ai_ci becomes utf8mb4_0900_ai_ci, _as_cs becomes utf8mb4_0900_as_cs, and anything else lands on the closest 0900 form. The pre-check reports the count as a note rather than something to go and fix, because a MariaDB source is dumped with MariaDB's own dump tool and the dump is normalized for MySQL before it is loaded, which is where that rewrite happens along with stripping the sandbox header and a sql_mode flag MySQL does not accept. The one thing worth doing afterwards is spot-checking sort-sensitive queries, since the two UCA versions order some strings a little differently. It also warns you that MySQL authenticates with caching_sha2_password where MariaDB uses its own plugin: clients on the pooler port are unaffected, and a client on the direct port needs a driver that speaks it.
One thing the pre-check no longer flags: a MariaDB JSON column is LONGTEXT plus a CHECK constraint calling json_valid(), and that arrangement loads on MySQL unchanged, since MySQL 8 has json_valid() and CHECK constraints of its own. The column stays LONGTEXT rather than becoming MySQL's native JSON type, so ALTER it after the copy if you want the -> operator or JSON indexes.
Treat it as a heads-up rather than a guarantee. It is read-only and best-effort: a parked database is not woken just to inspect it, the probe can fail on its own, and it only looks for the hazards on that list, so a copy can still stop on something it never saw. The backstop is on the other side. Layerbase compares row counts table by table once the copy finishes and shows you the result, and nothing is archived until you say so, so read that comparison before you switch anything over.
If you would rather do it by hand, the manual route still works: create a MySQL database on Solo, dump the MariaDB one with the same command above, and load it with the mysql client. Because the two share the wire protocol your application does not change, only the connection string does. The collation rewrite is something the Convert tab does for you and a hand-run dump does not, so do it yourself before you load: MariaDB writes its own collation names into a dump and MySQL does not carry MariaDB's aliases, so read the CREATE TABLE lines, see what character set and collation your tables actually declare, and map anything uca1400 onto the utf8mb4_0900 equivalent.
What $5/mo buys, concretely: two databases with 10 GB of storage, up to 100 concurrent connections, three instant branches per database, daily backups with seven-day retention, and a 768 MB always-on pool. Pinning MySQL to that pool draws the full 768 MB, so the database you pin never sleeps and the one you do not behaves like a free database, hibernating when idle and waking on connect.
Two related posts if this class of problem interests you: what a SQLite import can silently get wrong is the same failure mode in a different engine, and database dump determinism covers why two dumps of identical data do not always match byte for byte.
FAQ
Is there free MySQL hosting on Layerbase?
No. MySQL starts on the Solo plan at $5/mo, because a MySQL server idles at around half a gigabyte plus its ProxySQL sidecar, well past a free database's budget. MariaDB is on the Free plan, speaks the MySQL wire protocol, and takes your mysqldump file, so it is the free answer for a MySQL-shaped application. Free MySQL databases that predate the change were grandfathered rather than moved.
Can MariaDB read a MySQL 8 dump?
Yes, on a current version. MariaDB 11.4.5 added aliases for MySQL's utf8mb4_0900_* collations, which removes the failure that older guides describe. What still needs handling is DEFINER clauses on views, triggers and routines, plus the fact that users and grants are not in the dump at all.
What does "Unknown collation: 'utf8mb4_0900_ai_ci'" mean?
Your target server predates the MySQL collation aliases. It is MySQL error 1273, and it means the CREATE TABLE named a collation the server does not know. Restore into MariaDB 11.4.5 or newer, or search and replace the collation name in the dump and accept a different sort order.
How do I fix "Access denied; you need the SUPER privilege" on import?
Strip the DEFINER= clauses from the dump. Your file contains views, triggers or routines stamped with an account from the old server, and creating an object owned by another account is a privileged operation you do not have on a managed database. The sed line in the DEFINER section above is the usual fix, and the three information_schema queries next to it tell you whether you need it at all.
Do my MySQL drivers work against MariaDB?
Yes. MariaDB speaks the MySQL wire protocol, so mysql2, Prisma, Drizzle, PDO, and the mysql and mariadb command line clients all connect without a code change. Where the two engines genuinely diverge is features, not connectivity, and MySQL vs MariaDB walks through the differences that matter.
Will my emoji survive the move?
Only if the columns holding them are already utf8mb4. A column declared utf8 on an older MySQL is utf8mb3, holds three bytes per character, and cannot store emoji at all. It restores without complaint into MariaDB and stays broken. Query information_schema.COLUMNS for anything that is not utf8mb4 and convert those tables after the restore.
Why did my first connection time out?
A free MariaDB sleeps after 30 minutes idle and wakes on connect, and the cold start takes about 20 seconds. mysql2 gives up after 10 by default, so the first attempt after a quiet night fails and the retry succeeds. Set a 30 second connect timeout, start the database from its page before you connect, or put it on a paid plan and pin it always-on.
Can I convert a MariaDB database to MySQL in the dashboard?
Yes. The Convert tab supports MySQL and MariaDB in both directions, Redis and Valkey in both directions, and SQLite to libSQL, and either MySQL-family direction can move your host, port and password onto the new database so your connection string keeps working. MariaDB to MySQL needs Solo, because that is the plan MySQL starts on. The conversion is non-destructive: it creates a new database and leaves the original alone until you archive it, and a pre-check looks first for the things MySQL cannot parse, meaning sequences and MariaDB-only column types. Collations need no work from you: the dump is normalized for MySQL on the way across, so MariaDB's uca1400 collations are rewritten onto MySQL's utf8mb4_0900 family, which can order some strings slightly differently. That check is best-effort rather than a promise, so read the row-count comparison Layerbase runs after the copy before you archive the MariaDB database.
Where to put it
Create the target first, then dump, so you are not sitting on a file with nowhere to go. A MariaDB database on the Free plan costs $0 with no card and takes a mysql client restore like any other server. Start there, run your test suite against it, and find out how much of the MySQL-versus-MariaDB argument applies to your schema before you pay anything.
Keep reading
- Moving a MySQL database off cPanel shared hostingYour database is on a shared host that binds MySQL to localhost, runs a version you did not pick, and keeps the only backup. Here is the whole move: getting a dump that is actually complete, landing it on managed MariaDB, repointing the app, and the parts of shared hosting you will genuinely miss.
- Northflank alternatives: a preview environment is not a database branchNorthflank gives every pull request its own stack, and the database in that stack starts empty unless you seed it or restore it from a backup you already had. Here is exactly how their forks work, what a copy-on-write branch does differently, what each one costs while a PR sits open, and the cases where Northflank is the right answer.
- Aiven alternatives: one plan instead of one bill per serviceAiven prices every service on its own hourly meter, so a Postgres plus a MySQL plus a Valkey is three plans and three line items, at three different prices. Here is the arithmetic against a flat Layerbase plan, the real shape of both free tiers, and the four things Aiven does that we do not do at all.
- PlanetScale has no free tier. Here is where the $5 databases live now.The Hobby plan closed in March 2024 and PlanetScale docs now say plainly that there is no free plan. Here is what replaced it, what $5 a month actually buys in 2026, and when paying PlanetScale is still the right call.