在我粗略的研究中,我无法找到关于SELECT INTO OUTFILE
提供的好处的明确答案INSERT INTO ... SELECT
。在阅读与InnoDB 表上有关锁相关的文档时,它指出:INSERT INTO ... SELECT
对插入到 T 的每一行设置一个不带间隙锁的独占索引记录。如果事务隔离级别为 READ COMMITTED 或启用了 innodb_locks_unsafe_for_binlog,并且事务隔离级别不是 SERIALIZABLE,则 InnoDB 将 S 上的搜索作为一致读取(no锁)。否则,InnoDB 在 S 中的行上设置共享的 next-key 锁。
为了避免锁定INSERT INTO ... SELECT
似乎我必须确保隔离级别是READ COMMITTED
避免在查询期间锁定源表。
但是,我还没有找到任何关于 locks 和 usingSELECT INTO OUTFILE
的权威答案,甚至没有 MySQL文档参考 lock 信息。
我的目标是避免在查询运行时锁定源表以避免连接堆叠。
您应该使用SELECT ... LOCK IN SHARE MODE。为什么 ?
在你的情况下,你可以尝试这个
这将执行两个
SELECT
查询SELECT
锁定您希望的表中的行SELECT
要执行SELECT ... INTO OUTFILE
就个人而言,我认为您不必如此严厉。事务隔离应该足够聪明,以实现这个原子
SELECT
并为INSERT
. 我知道我说should be
这就是为什么你首先问你问题。无论您是
SELECT ... INTO OUTFILE
作为一个命令执行还是以我建议的严厉方式执行,源表的行数据都将是完全可读的。试试看 !!!
更新 2014-12-10 15:12 EST
你的评论
它们在操作上是不同的
SELECT INTO OUTFILE
创建一个文本文件INSERT INTO SELECT
从结果中加载一张表SELECT
更新 2014-12-11 12:21 EST
在这种情况下,我唯一能想到的是数据的时间点以及您使用它的时间。对于这两种类型的操作,都会有一些隐式共享锁定。
使用
SELECT INTO OUTFILE
,您正在准备结果并将其保存在外部。在加载过程中使用将数据加载到表中LOAD DATA INFILE
不会涉及任何共享锁定。请记住,这SELECT INTO OUTFILE
会产生磁盘 I/O,并且在此过程中仍然会施加一些缓存。使用
INSERT INTO SELECT
,共享锁可能必须在 InnoDB 中存活更长时间,因为您正在锁定行并使用这些相同的行插入到另一个表中。因此,如果我正在寻找性能奖励,我会给予优势,
INSERT INTO SELECT
因为您正在执行相同数量的共享行锁定,单个操作的磁盘 I/O 必须小于单独SELECT INTO OUTFILE
和后续的LOAD DATA INFILE
. 当然,您必须将这两种方法与您的数据集进行比较。一个数据集的性能奖励可能是另一个数据集的性能成本。更新 2014-12-17 00:00 EST
你的评论
唯一的权威回应来自 MySQL 文档。
首先,MySQL 文档LOAD DATA INFILE是怎么说的?
两段后,它说
当您查看插入语句的速度时,它会说:
此时事情开始看起来有点模糊,因为您必须根据存储引擎调整加载过程。MyISAM 在此语句中相当直接,因为大容量插入缓冲区仅用于 MyISAM,而 LOAD DATA INFILE 将利用大容量插入缓冲区。InnoDB 不会。
看看这个 InnoDB 的图示(Percona CTO Vadim Tchachenko)
调整选项还有其他考虑因素,但
LOAD DATA INFILE
实际上会将所有内容放入 InnoDB 缓冲池,通过日志缓冲区、双写缓冲区、插入缓冲区(如果目标表具有非唯一索引)、重做日志(ib_logfile0、ib_logfile1)和表的物理文件。这就是 LOAD DATA INFILE 的好处必须被取消的地方。我写过这个
Feb 06, 2012
: LOAD DATA (400k rows) INFILE 大约需要 7 分钟,无法杀死“记录慢查询”进程?Apr 20, 2012
:为什么 'LOAD DATA INFILE' 比普通的 INSERT 语句快?Jul 13, 2012
:从 infile 加载 Mysql 卡在硬盘上等待Jan 11, 2013
: MySQL LOAD DATA INFILE 在使用 InnoDB 引擎进行几次输入后减慢了 80%结语
正如我在之前对这个答案的更新中已经说过的那样
基本上,您必须
SELECT INTO OUTFILE/LOAD DATA INFILE
针对INSERT INTO SELECT
. 它可能是一个数据集的 6 个,一个数据集的六个,另一个数据集的陆上胜利。MySQL Docs 和我过去的帖子中所说的一切,我仍然对
INSERT INTO SELECT
. 您只需要测试这两种方法。