MySQL的大型后台更新

时间:2015-11-11 02:01:26

标签: mysql bulkinsert

我正在构建一个由MySQL支持的Web服务,该服务定期(例如,每天两次)从外部源缓存和索引数据。更新例程是修改缓存数据的唯一方法;对于其余的服务,此数据是只读的。此外,通过对外部源的多个HTTP请求来检索数据。请求数与检索的数据量成比例。假设组合时,数据不适合内存。我正在努力做到以下几点:

  1. 从服务的其余部分的角度来看,更新是原子的。该服务不应提供半更新的数据。
  2. 批量插入新数据的速度相当快。更新和插入不应使用单独的事务,而应在单个事务中运行。最后应该有一个提交。
  3. 对于这些更新,尽可能少地中断其余服务。在更新发生时,批量更新不应阻止其他会话访问旧数据。
  4. 我正在使用InnoDB。

    假设我有一个名为webservice的数据库,其中包含一个名为data的表。显而易见的首次尝试更新数据如下:

    START TRANSACTION;
    INSERT INTO `data`(`row1`, `row2`, `row3`) VALUES ('val1', 'val2', 'val3');
    INSERT INTO `data`(`row1`, `row2`, `row3`) VALUES ('val4', 'val5', 'val6');
    UPDATE `data` SET `row2` = 'val7' WHERE `id` = 3;
    /* And so on for a very large number of INSERTs and UPDATEs. */
    COMMIT;
    

    据我所知,这满足1和2,但违反了3。

    我想到了另一种似乎满足1,2和3的解决方案。这使用了" temp"将插入新数据的另一个数据库中的表,然后交换表。

    START TRANSACTION;
    DROP TABLE IF EXISTS `webservice_temp`.`data`;
    CREATE TABLE `webservice_temp`.`data` LIKE `webservice`.`data`;
    INSERT INTO `webservice_temp`.`data`
      SELECT * from `webservice`.`data`;
    INSERT INTO `data`(`row1`, `row2`, `row3`) VALUES ('val1', 'val2', 'val3');
    /* etc. */
    COMMIT;
    RENAME TABLE `webservice_temp`.`data` TO `webservice`.`data`;
    

    这是解决我问题的好方法吗?

1 个答案:

答案 0 :(得分:1)

如果您使用InnoDB,则可以使用START TRANSACTION WITH CONSISTENT SNAPSHOT使用您的第一种方法(并且它将满足所有三个要求)。这允许在开始事务处理时从原始数据的快照提供正在进行的读取请求。

WITH CONSISTENT SNAPSHOT修饰符为具有该功能的存储引擎启动一致读取。 这仅适用于InnoDB。

一致性读取意味着InnoDB使用多版本控制在某个时间点向查询提供数据库的快照。查询查看在该时间点之前提交的事务所做的更改,并且不会对以后或未提交的事务进行任何更改。

一种读取操作,它使用快照信息基于某个时间点显示查询结果,而不管同时运行的其他事务所执行的更改。如果查询数据已被另一个事务更改,则基于撤消日志的内容重建原始数据。 http://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_consistent_read