Я создаю веб-сервис под управлением MySQL, который кэширует и индексирует данные из внешнего источника через равные промежутки времени (скажем, два раза в день). Процедура обновления - единственное, что изменяет кэшированные данные; для остальной части службы эти данные доступны только для чтения. Кроме того, данные извлекаются через несколько HTTP-запросов внешнему источнику. Количество запросов пропорционально количеству извлеченных данных. Предположим, что при объединении данные не вписываются в память. Я стремлюсь к следующему:Большие обновления фона с MySQL
- Для того чтобы обновление было атомарным с точки зрения остальной части службы. Служба не должна обслуживать частично обновленные данные.
- Для массового ввода новых данных достаточно быстро. Обновления и вставки не должны использовать отдельные транзакции, но работать в одной транзакции. В конце должна быть одна фиксация.
- Чтобы эти обновления прерывали остальную часть службы как можно меньше. Массовое обновление не должно блокировать другие сеансы от доступа к старым данным во время обновления.
Я пользуюсь 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`;
Является ли это хорошим решением моей проблемы?
Это так! Я использую InnoDB. Это похоже на решение, которое я ищу. – mooiamaduck