Cron作业中的MySQL事务

时间:2017-03-23 13:32:51

标签: mysql innodb

我的Ubuntu服务器上有一个PHP DAEMON,它在InnoDB中插入大量数据。使用该平台的人也在使用相同的表格。

DAEMON未在TRANSACTION模式下运行时,对于100,000个插入使用大约60-70秒。在TRANSACTION模式下运行时,BEGIN .... COMMIT它使用15-20秒。

然而,TRANSACTION模式会锁定表格,并阻止使用该平台的用户在执行DAEMON TRANSACTION时执行插入操作吗? 当然,锁定用户操作超过20秒的表是不可取的:)

我正在以500和500的批量插入一个FOR循环INSERT INTO(col1,col2)VALUES(a,b)等。这很好,并且运行顺畅,但是我是如果我在循环之前发出BEGIN,并且在循环之后发出COMMIT,则能够显着加快进程,但这意味着BEGIN / COMMIT之间的时间超过60秒。但是当系统进行数十万次插入时,使用该平台的人可以对同一个表进行插入。系统是否会为用户插入生成Inserts帐户,或者用户是否必须等待XX秒才能处理插入?

2 个答案:

答案 0 :(得分:0)

根据您的描述,您使用启用了默认autocommit模式的innodb,并在循环中逐个插入记录。自动提交模式意味着每个插入都封装在自己的事务中,这很好但很慢,因为每个记录都单独保存到磁盘中。

如果您将循环插入begin - commit语句中的记录,则所有插入都在单个事务中运行,并且仅在commit时持久保存到磁盘一次发布 - 这就是你体验速度增益的原因。

无论您插入记录的方式如何,innodb都会使用锁定。但是,innodb only locks the record being inserted

  

INSERT在插入的行上设置独占锁。这个锁是一个   索引记录锁,而不是下一键锁(即没有间隙锁)   并且不会阻止其他会话之前插入间隙   插入的行。

     

在插入行之前,有一种称为插入的间隙锁   意图间隙锁定设置。此锁定表示插入的意图   这样一种方式,多个事务插入到同一个索引中   如果它们没有插入相同的间隙,则不必等待彼此   在差距内的位置。假设有索引记录   值4和7.尝试插入值的单独事务   分别为5和6,以插入意图锁定4和7之间的间隙   在获取插入行上的独占锁之前锁定,但是   不要互相阻塞,因为这些行是非冲突的。

这意味着,如果事务打开的时间较长,只插入记录,则不会干扰将记录插入同一个表的其他用户。

请注意,在循环中发出单个insert语句是将大量数据插入MySQL的效率最低的方法。

使用bulk insert(在循环中构建单个insert语句并在循环后执行它,注意max_allowed_packet设置:

  

使用VALUES语法的INSERT语句可以插入多行。至   执行此操作,包括多个列值列表,每个列值都包含在其中   括号并用逗号分隔。示例:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

或使用load data infile声明。

这两个解决方案可以显着加快数据插入速度,也不会导致表锁定。

答案 1 :(得分:0)

计划A:LOAD DATA。缺点:这需要将数据写入文件。如果它已经在文件中,那么这是最好的方法。

计划B:“已批量INSERTs” - 构建INSERT INTO t (a,b) VALUES (1,2), (3,4), ...并执行它们。分批进行100-1000。对于大量的1行BEGIN,这比COMMIT .. INSERTs更快。有autocommit=ON。锁定/阻止将是最小的,因为每个“交易”将只有100-1000行的价值。

让我们看看SHOW CREATE TABLEINDEXes,尤其是UNIQUE索引会对性能产生影响。我们可以进一步建议。

如果这是一个“数据仓库”应用程序,那么我们应该讨论“摘要表”。这些会大大减轻“读者”的负担,减少Fact表上索引的需要,防止锁定/阻塞,因为他们会读取不同的表。

此外,UUID的表现非常糟糕。

桌子有多大?你有多少RAM? innodb_buffer_pool_size的价值是什么?