导入非常大的 SQL 文件时单次提交 (MySQL)

Single commit when importing very large SQL files (MySQL)

我正在尝试将大型 SQL 文件(> 2.5 Gb)恢复到 Windows 上的 MySQL 数据库中。

我无法编辑这些文件以在文件开头添加类似 SET autocommit=0; 的文本(这是缩短导入时间所必需的)。

我也无法使用 source,因为它会输出到屏幕(非常慢)并且即使文件中有任何错误也会继续执行。例如:

mysql> CREATE DATABASE IF NOT EXISTS dbname;
mysql> USE dbname;
mysql> SET autocommit=0;
mysql> source file.sql;
mysql> COMMIT;

是否可以在导入仅适用于当前会话的 SQL 文件之前和之后执行 运行 任意命令?我已经尝试了以下两种方法,但都没有对 Windows 起作用(在这两种情况下,第二个操作都被忽略):

mysql -u username -p -e "SET autocommit=0;" dbname < file.sql

或者,

mysql -u username -p < initial_commands.sql < file.sql

如果可能的话,我不想在每次执行此操作时都更改全局 autocommit 设置,然后必须记住将其更改回来(而且我不确定如果没有最终 COMMIT;).

也许有一种方法可以使用 BEGIN ... COMMIT; 而不是关闭自动提交?

我很乐意接受必须做这种事情的人的任何建议!

(echo set autocommit=0; && type file.sql && echo. && echo commit;) | mysql -u username -p passwd

只需使用管道而不是输入重定向,对命令使用 echo,对换行符使用 echo.

你的目标可能会适得其反。也就是说,将整个负载转换为单个事务可能比增量提交慢。

set autocommit=0 意味着以后(直到 commit)的所有插入(和其他写入)都需要记录潜在的 ROLLBACK。首先,常规的日志记录机制可以写入一堆。但是,在某些时候,一个更复杂的机制开始出现。这涉及更多的磁盘 I/O,这是数据库中最慢的部分。

另一种方法是删除 "commit" 进程的重要部分 -- fsync 以刷新已提交的事务。 innodb_flush_log_at_trx_commit 控制这样的。对于 "secure",默认值可能是 =1。许多人 运行 使用 =2 这不太安全,但将 fsync 限制为每秒一次。 "inseccure" 部分是,如果出现电源故障,最后一秒内的任何事务 运行 可能已被客户端确认并实际保存到磁盘。

由于该设置可能必须在连接之前完成,请考虑一个简单的 3 行 .bat 脚本(文件):

mysql -e 'SET GLOBAL innodb_flush_log_at_trx_commit = 2'
mysql dbname < file.sql
mysql -e 'SET GLOBAL innodb_flush_log_at_trx_commit = 1'

我的回答晚了,但可能对未来的读者有所帮助。

我遇到了同样的问题。在阅读 MySQL documentation on MySQL command options 时,我发现您可以使用 --init-command 参数。

因此您的命令行将很简单:(-v 详细且可选)

mysql --init-command="SET autocommit=0;" -v < sql_file.sql