Make a local MyISAM backup with mysqlhotcopy
You will make a physical copy of one or more MariaDB databases on the same Linux machine, then check that the destination contains the copied database files. Allow about fifteen minutes for a small database, plus the time needed to copy its files. This guide describes the installed MariaDB 10.11-era command: package mariadb-client version 1:10.11.14-0ubuntu0.24.04.1. On this system, mysqlhotcopy is a symlink to mariadb-hotcopy.
The route
Jump straight to the step you need, or tick off Done means at the end.
There is a hard boundary: this tool backs up MyISAM and ARCHIVE tables. It is a local file-copy utility, not a general remote backup client, and it does not provide a suitable copy of an InnoDB database. For a mixed or transactional workload, choose a backup tool designed for those engines instead.
1. Check the command and the storage engine
Start with read-only checks. No elevated privileges are needed for these commands:
$ command -v mysqlhotcopy
/usr/bin/mysqlhotcopy
$ readlink -f /usr/bin/mysqlhotcopy
/usr/bin/mariadb-hotcopy
$ mysqlhotcopy --help
/usr/bin/mysqlhotcopy Ver 1.23
Usage: /usr/bin/mysqlhotcopy db_name[./table_regex/] [new_db_name | directory]
$ dpkg-query -W -f='${Package} ${Version}\n' mariadb-client
mariadb-client 1:10.11.14-0ubuntu0.24.04.1
The help text is useful for confirming the binary and the option spelling, but the installed manual is the contract for this guide. Before copying anything, establish that the tables you intend to back up are MyISAM or ARCHIVE. A query such as this reads metadata and changes no data:
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'APP_DB'
ORDER BY TABLE_NAME;
Replace APP_DB with the database name. Stop if the result contains InnoDB or another engine. Do not assume that a database is safe to copy just because some of its tables are MyISAM.
2. Prepare permissions and a destination
The MariaDB account needs SELECT, RELOAD and LOCK TABLES privileges, and the operating-system account running the command needs read access to the table files and write access to the destination. The command locks tables and flushes them before copying, so plan for a brief write pause and run it during a suitable maintenance window.
Create a new, empty destination on the same machine. The destination must not be a live MariaDB data directory:
$ install -d -m 0700 /srv/backups/mariadb/APP_DB-2026-09-25
$ test -w /srv/backups/mariadb/APP_DB-2026-09-25 && echo 'destination is writable'
destination is writable
Use a path owned by the account that will run the backup. If the MariaDB data files are readable only by a privileged account, use the smallest required elevation for the backup command, for example sudo mysqlhotcopy .... Do not make the whole backup tree world-readable: a physical copy can contain the database contents.
Checkpoint: you should now have a local destination with enough free space, an account with the four required forms of access, and a confirmed engine list containing only MyISAM or ARCHIVE.
3. Keep credentials out of the command line
The -p option requires its password value immediately, and putting that value on the command line can expose it through shell history or process inspection. Prefer an option file group. The manual accepts settings from the [mysqlhotcopy] and [client] groups:
[mysqlhotcopy]
user=backup_user
password=REPLACE_WITH_A_REAL_PASSWORD
socket=/run/mysqld/mysqld.sock
Write this in a file readable only by the account that runs the command, such as ~/.my.cnf, and replace the placeholder before use:
$ chmod 600 ~/.my.cnf
$ test "$(stat -c '%a' ~/.my.cnf)" = 600 && echo 'option file permissions are restricted'
option file permissions are restricted
Do not paste a real password into a shared terminal transcript. If you have already exposed one in history or process output, rotate it according to your database access procedure.
4. Run a single-database copy
With the server running and the destination empty, copy one database:
$ mysqlhotcopy APP_DB /srv/backups/mariadb/APP_DB-2026-09-25
The command uses FLUSH TABLES, LOCK TABLES and a local file copy. It uses cp by default. A successful run should return to the shell without an error. Verify the result from the shell rather than relying on a guessed progress message:
$ find /srv/backups/mariadb/APP_DB-2026-09-25 -maxdepth 1 -type f -printf '%f\n' | sort
APP_TABLE.MYD
APP_TABLE.MYI
APP_TABLE.frm
$ test -r /srv/backups/mariadb/APP_DB-2026-09-25/APP_TABLE.MYD && echo 'table data copy is readable'
table data copy is readable
The file names and extensions depend on the tables in your database and MariaDB version. The useful check is that the expected database directory and table files exist and are readable, not that this exact listing appears.
5. Copy selected tables or several databases
To select tables in one database, append a slash-delimited regular expression after the database name. This example selects tables whose names start with audit_:
$ mysqlhotcopy 'APP_DB./^audit_/' /srv/backups/mariadb/APP_DB-audit-2026-09-25
Prefix the expression with ~ to exclude matching table names, as documented by the installed manual. Review a regular expression carefully before running it; an accidental match can make a backup incomplete without making the command itself fail.
For several databases, put each database name before the final destination:
$ mysqlhotcopy APP_DB REPORTING_DB /srv/backups/mariadb/mysqlhotcopy-2026-09-25
Keep each destination separate from the live data directory. Do not use shell globs in place of database names unless you have deliberately checked what the shell expands them to.
6. Handle an existing destination deliberately
Do not casually rerun the command against a directory containing a previous copy. By default, an existing target is an error. If you need the tool's built-in replacement behaviour, choose it explicitly:
--allowoldrenames an existing target with an_oldsuffix.--keepoldkeeps that renamed directory instead of deleting it when the new copy finishes.--addtodestleaves the target in place and adds files to it.
These options change on-disk state. The safest recovery from a wrong destination is to stop, preserve the directories, and inspect them. Once you have independently verified the new copy, remove an unwanted old copy with an explicit path and your normal retention procedure. That deletion is irreversible and is not part of the backup command.
7. Use dry-run and diagnose failures
Before a change of destination or selection rule, --dryrun (or -n) reports actions without performing them:
$ mysqlhotcopy --dryrun APP_DB /srv/backups/mariadb/APP_DB-2026-09-25
Use the output to check the source and destination, but do not treat a dry run as a backup. If authentication fails, check the option file group, socket path and account privileges. If a table cannot be read, check operating-system permissions on the database files. If copying fails part-way through, treat the destination as incomplete, preserve it for investigation if useful, and rerun to a new directory after fixing the cause.
The command supports --socket for a local Unix socket, or --host and --port for a TCP connection to the local server. These options change how the client connects; they do not make the file copy remote. A remote server's data directory is outside this tool's scope.
Done means
- The installed command and package version were checked.
- Every selected table is MyISAM or ARCHIVE, and the source is on the same machine.
- The account has file read access plus SELECT, RELOAD and LOCK TABLES.
- Credentials are stored in a restricted option file, not in the command line.
- The copy was made to a separate, protected destination during an acceptable lock window.
- The destination contains the expected database and table files, and an incomplete or old copy has not been mistaken for a verified backup.