How to import a SQL file into MySQL or MariaDB
Create the target database, then run mysql -u root -p mydb < mydb.sql. For a gzipped dump, use gunzip -c mydb.sql.gz | mysql -u root -p mydb; inside the client, source mydb.sql does the same. Failed imports almost always come down to a missing database, a version or collation mismatch, or privileged lines in the dump, and each has a short fix below.
Check what kind of dump it is
A dump of one database loads into whatever database you name. A dump made with --databases or --all-databases has its own CREATE DATABASE and USE lines, which decide where the data goes. Check which you have (for a .gz file, pipe gunzip -c mydb.sql.gz into the same grep without the file name):
grep -n -m 5 -E '^(CREATE DATABASE|USE )' mydb.sqlNo output means a single-database dump. head -n 5 mydb.sql shows which program wrote it: -- MySQL dump or -- MariaDB dump, followed by the version.
A dump with USE lines writes into the database it names, so on the live server it overwrites the original even when you meant to restore a copy. Edit those lines first, or use a separate server.
Create the database and import
Making the dump is covered in MySQL backups with mysqldump. On MariaDB you can type mariadb wherever this guide says mysql.
mysql -u root -p -e "CREATE DATABASE mydb CHARACTER SET utf8mb4"mysql -u root -p mydb < mydb.sql-u root -plogs in as root and prompts for the password, keeping it out of shell history. Any account that can create tables, views, triggers and routines there will do.mydbis the database the statements run in. Leave it out for a dump with its ownUSElines.- If root logs in through the Unix socket (the Ubuntu and Debian default), run
sudo mysql mydb < mydb.sqlinstead.
The client stops at the first error, reports the line of the failing statement, as in ERROR 1273 (HY000) at line 25: Unknown collation: 'utf8mb4_0900_ai_ci', and exits with status 1. Fix the cause and import again into an empty database. --force carries on past errors, but the result is missing whatever failed; use it only to list every problem in one pass.
Import with source inside the client
CREATE DATABASE IF NOT EXISTS mydb;
USE mydb;
source /home/deploy/mydb.sqlsource (or \.) is a client command, not SQL, so the path is on the machine running mysql. Interactively, it prints each error and keeps going, so failures can scroll past unnoticed; for big files the shell form is easier to check.
Import a gzipped dump
gunzip -c mydb.sql.gz | mysql -u root -p mydbgunzip -c (or zcat) writes the SQL to the pipe and leaves the file untouched. Redirecting the .gz file straight into mysql fails with an ASCII '\0' appeared in the statement error.
If the .gz file is cut short, gunzip fails partway, but mysql loads whatever arrived and exits 0. Test the file with gzip -t mydb.sql.gz first, and use set -o pipefail in scripts so the pipeline fails when any part of it does.
Show progress on a large import
The client prints nothing while it works. pv (Pipe Viewer) shows how much of the file has been read, the speed and the time left. It is a separate package: sudo apt install pv on Debian and Ubuntu. Its progress bar and the password prompt garble each other, so put the login in ~/.my.cnf, which the client reads on its own, and chmod 600 the file:
[client]
user=root
password="your-password-here"pv mydb.sql.gz | gunzip | mysql mydbThe percentage is the share of the compressed file read so far; heavily indexed tables load slower than their share. Delete ~/.my.cnf afterwards if you do not want the password left on disk.
Make large imports faster
Check what the dump already does. Unless made with --compact, mysqldump and mariadb-dump files switch off unique and foreign key checks near the top, switch them back on at the end, and use multi-row INSERTs, which the MySQL manual says import quickly as they are:
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;For SQL from other tools, or a --compact dump, set the same session variables yourself. --init-command runs one statement as the client connects:
mysql --init-command="SET SESSION foreign_key_checks=0, unique_checks=0" -u root -p mydb < export.sqlunique_checks=0lets InnoDB batch its secondary index writes. The manual's condition: be certain the data contains no duplicate keys.foreign_key_checks=0lets tables load in any order. Rows loaded this way are not re-checked when the checks come back on, so use it only for data that was consistent when dumped.- Both last for this connection only and need no special privilege.
On a brand-new, empty MySQL server, ALTER INSTANCE DISABLE INNODB REDO_LOG; speeds up the first load; ALTER INSTANCE ENABLE INNODB REDO_LOG; turns logging back on. Never on production: a crash while it is off can corrupt the instance.
Run the import on the database server, not across a network. Beyond that, the format is the limit: every row is replayed and every index rebuilt. For very large databases, physical backups with XtraBackup restore far faster.
Character sets and --default-character-set
mysqldump and mariadb-dump write a SET NAMES line near the top, so client and server agree on the encoding. Files from other tools, --compact dumps and pieces cut from a dump may not have one. If grep -m 1 'SET NAMES' mydb.sql finds nothing, tell the client the encoding, or accented letters and emoji can be stored double-encoded (é where é should be):
mysql --default-character-set=utf8mb4 -u root -p mydb < export.sqlImport a single table
A dump of just that table (mysqldump mydb orders > orders.sql) imports like any other: it drops and recreates orders and leaves the rest alone. To take one table out of a full dump, restore the dump into a scratch database and copy the table across. With the login in ~/.my.cnf as above:
mysql -e "CREATE DATABASE mydb_scratch"gunzip -c mydb.sql.gz | mysql mydb_scratchmysqldump mydb_scratch orders | mysql mydbmysql -e "DROP DATABASE mydb_scratch"If the dump is too big to restore twice, cut the table out. mysqldump starts each table with a -- Table structure for table comment, so this keeps everything from the orders header to the next one:
gunzip -c mydb.sql.gz | sed -n '/^-- Table structure for table `orders`/,/^-- Table structure for table/p' > orders.sqlThe piece lacks the dump header, so load it with the settings the header would have set:
mysql --init-command="SET SESSION foreign_key_checks=0" --default-character-set=utf8mb4 -u root -p mydb < orders.sqlThis needs the comments, which --compact and --skip-comments dumps lack; if orders is the last table, the piece also picks up the views and routines after it. For one database out of an --all-databases dump, create it and run mysql --one-database shop -u root -p < all-databases.sql; the manual calls the option rudimentary, since it filters only on USE lines.
Check the import worked
An import without errors is a good sign, not proof. Count the objects on the source and the copy; the numbers should match:
SELECT
(SELECT COUNT(*) FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'mydb' AND TABLE_TYPE = 'BASE TABLE') AS tables_count,
(SELECT COUNT(*) FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'mydb' AND TABLE_TYPE = 'VIEW') AS views_count,
(SELECT COUNT(*) FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'mydb') AS routines_count,
(SELECT COUNT(*) FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'mydb') AS triggers_count;Count rows in the tables that matter with SELECT COUNT(*), not with TABLE_ROWS from information_schema, which for InnoDB can be 40 to 50 percent off. To compare contents, CHECKSUM TABLE reads every row and returns one number:
CHECKSUM TABLE mydb.orders;Different values mean the tables differ; equal values mean they almost certainly match. The value depends on row format, so compare the same server version, and the table is read-locked while it runs. Whether your application starts against the copy is the real test: see how to test a backup restore.
Errors and how to fix them
| Error | Cause and fix |
|---|---|
ERROR 1045 (28000): Access denied for user 'app'@'localhost' (using password: YES) | Wrong user, password or host. (using password: NO) means you left out -p. If root uses socket login, run sudo mysql. |
ERROR 1049 (42000): Unknown database 'mydb' | The database does not exist yet. Create it first. |
ERROR 1046 (3D000) at line 22: No database selected | A single-database dump has no USE line. Name the database on the command line. |
ERROR 1050 (42S01) at line 25: Table 'orders' already exists | The dump has no DROP TABLE lines (made with --compact or --skip-add-drop-table). Import into an empty database. |
ERROR 1064 (42000) at line 31: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '…' at line 1 | A statement this server does not understand: often a dump from a newer version or the other product, or a file that is not plain SQL. Parsing stopped at the text after near; view it with sed -n '31p' mydb.sql | cut -c1-300 and edit it. MariaDB says MariaDB server version. |
ERROR 2006 (HY000) at line 2240: MySQL server has gone away or ERROR 2013 (HY000) at line 2240: Lost connection to MySQL server during query | Usually a statement bigger than max_allowed_packet (by default 64MB on the server, 16MB in the client): raise both (below). Otherwise check the server log for a crash or out-of-memory kill. MariaDB's client says Server has gone away. |
ERROR 1227 (42000) at line 18: Access denied; you need (at least one of) the SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN privilege(s) for this operation | A dump from a MySQL server with GTIDs: it runs SET @@SESSION.SQL_LOG_BIN= 0; and sets @@GLOBAL.GTID_PURGED, which managed databases rarely allow. Re-dump with --set-gtid-purged=OFF, or strip the lines (below). |
ERROR 1227 (42000) at line 1514: Access denied; you need (at least one of) the SUPER or SET_ANY_DEFINER privilege(s) for this operation | A view, trigger or routine names another account as DEFINER (MySQL 8.0 says SUPER or SET_USER_ID). Import as an admin, create that account first, or rewrite the definers (below). |
ERROR 1273 (HY000) at line 25: Unknown collation: 'utf8mb4_0900_ai_ci' | A MySQL 8 dump going into MariaDB before 11.4.5, or into MySQL 5.7. Replace the collation (below). |
ERROR 1824 (HY000) at line 40: Failed to open the referenced table 'customers' | Foreign key checks are on and a child table came before its parent. Import with --init-command="SET SESSION foreign_key_checks=0". The same problem can show as ERROR 1215 (HY000): Cannot add foreign key constraint, or on MariaDB as error 1005 with errno: 150 "Foreign key constraint is incorrectly formed". Still failing with checks off? The column types must match and the referenced columns must be indexed. |
ERROR at line 1: Unknown command '\-'. | A dump from mariadb-dump 10.5.25, 10.6.18, 10.11.8, 11.0.6, 11.1.5, 11.2.4 or 11.4.2 starts with a sandbox-mode line the MySQL client does not understand. Skip line 1 (below). |
ERROR at line 1: ASCII '\0' appeared in the statement, but this is not allowed unless option --binary-mode is enabled and mysql is run in non-interactive mode. … | A compressed file went straight into mysql. Use gunzip -c in the pipe. |
Raise the packet limit on the server (admin account; new connections pick it up) and on the client:
SET GLOBAL max_allowed_packet = 1073741824;mysql --max-allowed-packet=1G -u root -p mydb < mydb.sql1G is the maximum. To keep it after a restart, add max_allowed_packet = 1G under [mysqld] in the server's config. To strip the GTID lines from a dump you cannot remake (the GTID set can span several lines, so the script skips to the closing semicolon):
gunzip -c mydb.sql.gz | awk '/^SET @@GLOBAL.GTID_PURGED/ {skip=1} skip {if (/;$/) skip=0; next} /^SET @@SESSION.SQL_LOG_BIN/ {next} {print}' | mysql -u root -p mydbTo make every view, trigger and routine belong to the account running the import:
sed -E 's/DEFINER=`[^`]+`@`[^`]+`/DEFINER=CURRENT_USER/g' mydb.sql > mydb-fixed.sqlTo replace MySQL 8's default collation with one every version knows (grep -o 'utf8mb4_0900_[a-z_]*' mydb.sql | sort -u lists any other 0900 collations; on MariaDB 10.10 or later, utf8mb4_uca1400_ai_ci follows newer Unicode sorting rules, as MySQL's does):
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' mydb.sqlTo skip the sandbox line of an affected MariaDB dump:
tail -n +2 mydb.sql | mysql -u root -p mydbFrequently asked questions
- How do I import a large SQL file into MySQL?
- Use the command-line client on the database server itself, watch it with pv, and raise max_allowed_packet if it fails with 'server has gone away'. For hundreds of gigabytes, a physical backup restores far faster.
- How do I import a .sql.gz file into MySQL?
- Decompress it in the pipe: gunzip -c file.sql.gz | mysql -u root -p mydb. The .gz file is left as it is.
- Can I import a MySQL dump into MariaDB?
- Usually. The common snag is MySQL 8's utf8mb4_0900_ai_ci collation, which MariaDB accepts only from 11.4.5; on older versions replace it with utf8mb4_unicode_ci.
- How do I skip errors when importing a SQL file?
- mysql --force continues past errors, but the database ends up missing whatever failed. Use it to list the problems, fix them, then import again into an empty database.
How this was checked
Commands, limits and prices were checked against these official pages, on October 4, 2026:
- MySQL 8.4 Reference Manual: mysql Client Options
- MySQL 8.4 Reference Manual: Executing SQL Statements from a Text File
- MySQL 8.4 Reference Manual: Reloading SQL-Format Backups
- MySQL 8.4 Reference Manual: mysqldump
- MySQL 8.4 Reference Manual: Bulk Data Loading for InnoDB Tables
- MySQL 8.4 Reference Manual: Redo Log (Disabling Redo Logging)
- MySQL 8.4 Reference Manual: FOREIGN KEY Constraints
- MySQL 8.4 Reference Manual: MySQL server has gone away
- MySQL 8.4 Reference Manual: Packet Too Large
- MySQL 8.4 Reference Manual: Server System Variables (max_allowed_packet)
- MySQL 8.4 Reference Manual: CHECKSUM TABLE Statement
- MySQL 8.4 Reference Manual: The INFORMATION_SCHEMA TABLES Table
- MySQL 8.4 Reference Manual: Stored Object Access Control
- MySQL 8.4 Server Error Message Reference
- MySQL 8.4 Client Error Message Reference
- MySQL Server 8.4 source: client/mysqldump.cc (dump header, GTID lines, table comments)
- MySQL Server 8.4 source: client/mysql.cc (error format, --binary-mode message)
- MySQL Server 8.4 source: sql/sys_vars.cc (sql_log_bin privilege check)
- MySQL Server 8.4 source: sql/auth/sql_authorization.cc (DEFINER privilege check)
- MariaDB Foundation: MariaDB Dump File Compatibility Change
- MariaDB Jira: MDEV-34203
- MariaDB documentation: Unicode
- MariaDB 11.4.5 Release Notes
- MariaDB documentation: mariadb-dump
- Ubuntu manpage: pv