在没有TRANSACTION的批量INSERT上重建MySQL暂停索引

时间:2011-04-10 18:16:13

标签: mysql transactions indexing

我有很多数据要将LOW_PRIORITY INSERT到表中。每次插入行时都会重建索引,这需要很长时间。我知道我可以使用事务,但是如果只有一行失败,我不希望整个集合失败。

有没有办法让MySQL停止在特定表上重建索引,直到我告诉它可以恢复?

理想情况下,我想插入1000行左右,设置索引做它的事情,然后插入接下来的1000行。

我不能使用INSERT DELAYED,因为我的表类型是InnoDB。否则,INSERT DELAYED对我来说是完美的。

不重要,但我使用PHP / PDO访问MySQL。您可以给予的任何建议将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:6)

ALTER TABLE tableName DISABLE KEYS
// perform inserts
ALTER TABLE tableName ENABLE KEYS

这将禁用所有非唯一索引的更新。缺点是这些索引也不会用于选择查询。

然而,您可以使用多插入(INSERT INTO表(...)VALUES(...),(...),(...),它们也将批量更新索引。

答案 1 :(得分:3)

AFAIK,对于那些使用InnoDB表的人,如果你不想在每个INSERT之后重建索引,你必须使用交易。

例如,要插入一批1000行,请使用以下SQL:

SET autocommit=0;
//Insert the rows one after the other, or using multi values inserts
COMMIT;

通过禁用自动提交,将在第一个INSERT启动一个事务。然后,一个接一个地插入行,最后,提交事务并重建索引。

如果在执行INSERT之一时发生错误,则不会回滚事务,但会向客户报告错误,该客户可以选择回滚或继续。因此,如果您不希望在INSERT失败的情况下回滚整个批处理,则可以记录失败的INSERT并继续插入行,最后提交事务处理结束。

但是,考虑到在事务中包装INSERT意味着在提交事务之前您将无法看到插入的行。可以将SELECT的事务隔离级别设置为READ_UNCOMMITTED,但在我对其进行测试时,SELECT非常接近{INSERT时,行不可见{1}}。查看我的post