繁体   English   中英

使用 MySQL 进行大型后台更新

[英]Large background updates with MySQL

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

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

我正在使用 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 的解决方案。这将使用另一个数据库中的“临时”表,其中将插入新数据,然后交换表。

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`;

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

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

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

一致读取意味着 InnoDB 使用多版本控制在某个时间点向查询呈现数据库的快照。 查询会看到在该时间点之前提交的事务所做的更改,而不会看到稍后或未提交的事务所做的更改。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM