Renaming a database becomes necessary when a schema name no longer matches an application, environment, or ownership boundary. A clean rename keeps connection strings, grants, backups, and monitoring aligned with the right data, which matters most during cutovers and long-lived production maintenance.
In MySQL and MariaDB, a database is a schema namespace for tables, views, routines, triggers, and events. Neither product exposes a general-purpose atomic RENAME DATABASE statement, so the safest cross-version workflow is to create the new schema, dump the old one, import it into the new name, then cut applications over after validation.
The operation is not instantaneous. Logical dumps need enough free disk space, –single-transaction only gives a consistent snapshot for transactional tables, and imported objects can still contain fully qualified references such as rename_source.table_name. Database-scoped grants are not copied automatically, and dropping the old schema does not remove its old grants, so plan a maintenance window and finish the rename with grant cleanup plus object-level validation.
Logical dumps do not provide an atomic rename. Pause writes, background jobs, and migrations that can change the source schema during the export and cutover window.
$ mysql --user=root --password --execute "SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='rename_source';" Enter password: +----------------------------+------------------------+ | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | +----------------------------+------------------------+ | utf8mb4 | utf8mb4_0900_ai_ci | +----------------------------+------------------------+
Add --host and --port when connecting to a remote server. On MariaDB, the returned collation name can differ from MySQL; use whatever the source schema reports.
$ mysql --user=root --password --execute "CREATE DATABASE rename_target CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;" Enter password:
No output indicates the schema was created.
$ mysqldump --user=root --password --single-transaction --quick --routines --triggers --events rename_source > /root/sg-work/backups/mysql/rename-source.sql Enter password:
Do not use --databases for a rename dump. That option adds CREATE DATABASE and USE statements that can restore into the original schema name instead of the target.
On MariaDB systems, use mariadb-dump when that is the installed dump client. Recent MariaDB releases may not ship a mysqldump compatibility binary.
$ ls -lh /root/sg-work/backups/mysql/rename-source.sql -rw-r--r-- 1 root root 7.3K Apr 9 14:43 /root/sg-work/backups/mysql/rename-source.sql
$ grep -n "rename_source\\." /root/sg-work/backups/mysql/rename-source.sql 87:/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `customers_ai` AFTER INSERT ON `customers` FOR EACH ROW INSERT INTO rename_source.audit_log (customer_id, action) VALUES (NEW.id, 'insert') */;; 110:/*!50106 CREATE*/ /*!50117 DEFINER=`root`@`localhost`*/ /*!50106 EVENT `cleanup_event` ON SCHEDULE EVERY 1 DAY STARTS '2026-04-09 14:42:37' ON COMPLETION NOT PRESERVE ENABLE DO DELETE FROM rename_source.audit_log WHERE id < 0 */ ;; 133:SELECT COUNT(*) AS customers FROM rename_source.customers ;;
If this search finds the old schema name inside views, routines, triggers, or events, edit or recreate those objects so they point at rename_target before you drop rename_source. Otherwise those objects can fail immediately after cutover.
$ mysql --user=root --password rename_target < /root/sg-work/backups/mysql/rename-source.sql Enter password:
Import into an empty target schema. If the import fails partway through, drop and recreate the target schema before retrying.
If the dump was created with mariadb-dump on MariaDB 11 or newer, import it with the matching mariadb client rather than the MySQL mysql client.
$ mysql --user=root --password --execute " SELECT s.schema_name, (SELECT COUNT(*) FROM information_schema.tables t WHERE t.table_schema=s.schema_name AND t.table_type='BASE TABLE') AS tables, (SELECT COUNT(*) FROM information_schema.tables v WHERE v.table_schema=s.schema_name AND v.table_type='VIEW') AS views, (SELECT COUNT(*) FROM information_schema.routines r WHERE r.routine_schema=s.schema_name) AS routines, (SELECT COUNT(*) FROM information_schema.triggers tr WHERE tr.trigger_schema=s.schema_name) AS triggers, (SELECT COUNT(*) FROM information_schema.events e WHERE e.event_schema=s.schema_name) AS events FROM ( SELECT 'rename_source' AS schema_name UNION ALL SELECT 'rename_target' AS schema_name ) s; " Enter password: +---------------+--------+-------+----------+----------+--------+ | schema_name | tables | views | routines | triggers | events | +---------------+--------+-------+----------+----------+--------+ | rename_source | 2 | 1 | 1 | 1 | 1 | | rename_target | 2 | 1 | 1 | 1 | 1 | +---------------+--------+-------+----------+----------+--------+
Differences usually mean the dump missed object types, the import failed partway through, or an object was skipped because it referenced the old schema incorrectly.
$ mysql --user=root --password --execute "SHOW GRANTS FOR 'app_user'@'localhost';" Enter password: +--------------------------------------------------------------------------------------------------------------+ | Grants for app_user@localhost | +--------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO `app_user`@`localhost` | | GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, EVENT, TRIGGER ON `rename_source`.* TO `app_user`@`localhost` | +--------------------------------------------------------------------------------------------------------------+
$ mysql --user=root --password --execute "GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, EVENT, TRIGGER ON rename_target.* TO 'app_user'@'localhost';" Enter password:
Copy the privilege list from the real SHOW GRANTS output. If access is granted through roles or multiple account entries, update those grants instead of assuming one direct GRANT statement covers everything.
Update DSNs, ORM configuration, backup jobs, scheduled tasks, and any application-side SQL that still names rename_source. Re-test views, routines, triggers, and events if the dump inspection step found fully qualified schema references.
$ mysql --user=root --password --execute "REVOKE SELECT, INSERT, UPDATE, DELETE, EXECUTE, EVENT, TRIGGER ON rename_source.* FROM 'app_user'@'localhost';" Enter password:
MySQL and MariaDB do not automatically remove database-level grants when the old schema is dropped. Clean up those grants explicitly so stale permissions do not remain on the account.
$ mysql --user=root --password --execute "DROP DATABASE rename_source;" Enter password:
DROP DATABASE permanently deletes the old schema. Keep the SQL dump until the new schema has been backed up and the cutover is fully accepted.