Являются ли множественные вставки mysql в одном запросе атомарными?

Я делаю несколько вставок в один запрос:

INSERT INTO table (c1, c2) VALUES (1,2),
                                  (2,3),
                                  (3,4),......
         ON DUPLICATE KEY UPDATE c2 = VALUES(c2)

Теперь предположим, что в запросе указано более десятков тысяч ЗНАЧЕНИЙ (отсюда многоточие)....

Может ли когда-нибудь быть случай, когда некоторые части ЗНАЧЕНИЙ удалось вставить/обновить в базу данных, но остальные не были вставлены/обновлены, возможно, из-за какой-то ошибки БД/сбоя/исчерпания памяти и т. д.?

Являются ли запросы mysql ВСЕМИ или ничего?

Верно ли, что для каждого выполненного запроса mysql все значения, указанные в запросе, будут плавно вставлены/обновлены, или ни одно из значений не будет вставлено/обновлено?


person pillarOfLight    schedule 05.02.2014    source источник
comment
Один вызов insert должен быть атомарным в любой базе данных, совместимой с ACID.   -  person Gordon Linoff    schedule 05.02.2014
comment
Почему бы вам не протестировать его? Вам не нужны сотни точек данных, чтобы протестировать его!   -  person gvee    schedule 05.02.2014
comment
возможный дубликат Является ли вставка/обновление объединения в MySQL атомарной операцией?   -  person Daniel    schedule 05.02.2014
comment
Однако таблицы @GordonLinoff MyISAM не совместимы с кислотой;)   -  person Johannes H.    schedule 05.02.2014
comment
@gvee почти невозможно проверить, как и во всех условиях гонки. если повезет, вы можете запустить 10000 тестов в системах, не совместимых с кислотой, и при этом иметь согласованные данные.   -  person Johannes H.    schedule 05.02.2014
comment
@ЙоханнесХ. . . . Что ж, думаю, это ответ на вопрос. Я не вижу этого в документации MySQL, но вижу в rackspace.com/knowledge_center/article/.   -  person Gordon Linoff    schedule 05.02.2014
comment
@GordonLinoff Ссылка на спецификацию находится в моем ответе   -  person Johannes H.    schedule 05.02.2014


Ответы (4)


Свойства ACID (атомарность, согласованность, изоляция, долговечность) используются для описания такого поведения в базах данных. Атомарность важна, только если мы имеем дело с одновременными изменениями. Для обеспечения согласованности должен быть достигнут определенный уровень изоляции. Однако чем более изолированно выполняется несколько транзакций, тем ниже обычно производительность СУБД. Таким образом, существует так называемый "уровень изоляции", в котором указано, какие ошибки может произойти в СУБД, а что нет.

Теперь MySQL реализует все уровни изоляции в базах данных INNODB, и вы можете выбрать для каждой транзакции: https://dev.mysql.com/doc/refman/5.1/en/set-transaction.html

Базы данных MyIsam не поддерживают транзакции, однако отдельные операции должны выполняться атомарно. (Источник: https://dev.mysql.com/doc/refman/5.0/en/ansi-diff-transactions.html). Обратите внимание, однако, что это НЕ гарантирует, что данные не изменятся между чтением и записью в одной операции - атомарность в терминах СУБД означает только то, что операция либо полностью выполнена, либо полностью пропущена. Это НЕ гарантирует изоляции, согласованности или долговечности.

person Johannes H.    schedule 05.02.2014
comment
Могу я спросить, за что был минус? Я не вижу ни комментариев, ни предложений по редактированию... - person Johannes H.; 05.02.2014
comment
. . . Есть злонамеренные downvoters там. Я думаю, что это хороший ответ. +1. - person Gordon Linoff; 05.02.2014
comment
@ЙоханнесХ. Возможно, это связано с тем, что ссылка MySQL указывала на немецкую документацию =) Исправлено. - person Ciro Santilli 新疆再教育营六四事件ۍ 07.07.2014
comment
Ой. Я даже не понял! Спасибо! - person Johannes H.; 08.07.2014
comment
@JohannesH., Итак, в приведенном выше примере, если мы используем Innodb, вы имеете в виду, что вставка 1000 строк будет либо «Все», либо «Ничего»? Возможно ли за половину суммы, например. Вставить 300, 500 или 800 строк? - person Pacerier; 18.12.2014
comment
@Pacerier Если это транзакция, то она либо фиксируется, либо полностью откатывается. Что это означает, зависит от выбранного вами уровня изоляции. - person Johannes H.; 26.12.2014
comment
@JohannesH., Нет, это явная транзакция. Это обычный одиночный оператор вставки. Используют ли отдельные операторы, вставляющие тысячи строк, преимущества фиксации или полного отката? - person Pacerier; 27.12.2014
comment
При включенной автоматической фиксации (по умолчанию) вы находитесь в транзакции, так что да. Если вы отключили его (по соображениям производительности или что-то еще), это сильно зависит от того, что вы подразумеваете под всем или ничего. Возможны ли сбои? У вас есть одновременные операции? Но в целом на это можно не рассчитывать. - person Johannes H.; 28.12.2014
comment
Если я запускаю php-скрипт, который вставляет несколько строк в mysql db. Предположим, что это занимает около 5 секунд. Через 5 секунд я закрываю скрипт, т.е. закрываю php-страницу в браузере или прерываю скрипт в консоли. Затем, как могут быть вставлены строки в db. Также сообщите ответ для 2 возможных вариантов использования. Во-первых, если несколько запросов mysql вставляют много-много строк, а во-вторых, если один запрос mysql вставляет несколько строк. Please answer. May the force be with you. - person Ankit; 11.05.2016
comment
@Ankit Прежде всего: если какая-либо операция с базой данных занимает 5 секунд, вам следует серьезно подумать о других решениях для всего, что вы делаете. Во-вторых: если все операторы уже были отправлены на сервер базы данных (возможно асинхронное выполнение, например, tihs), они будут выполняться, даже если скрипт завершится. Если их не было, то это зависит от того, сколько инструкций было отправлено. Если вы использовали транзакцию, и скрипт умирает до фиксации, изменения будут отменены (то есть в конце изменений нет). Если нет, то случилось то, что случилось, а то, что не случилось, еще не произойдет. - person Johannes H.; 11.05.2016
comment
@Ankit: Чтобы ответить конкретно на ваши варианты использования, нам потребуется дополнительная информация о вашем стеке сервера, какие библиотеки PHP вы используете и о вашем коде. ПОЖАЛУЙСТА, сделайте это отдельным вопросом в этом случае (не стесняйтесь указать мне на него, если вы это сделаете) - person Johannes H.; 11.05.2016
comment
Однако -1 для одиночных операций должен выполняться атомарно. Должен? Является ли многострочная вставка атомарной или нет? Это был вопрос - этот пост не отвечает на него. - person AndreKR; 30.08.2016

"Может ли когда-нибудь быть случай, когда некоторые части ЗНАЧЕНИЙ удалось вставить/обновить в базу данных, но остальные не были вставлены/обновлены, возможно, из-за какой-то ошибки/сбоя/нехватки памяти в базе данных? и т. д.?"

Поздний ответ, но, возможно, интересный: [ON DUPLICATE KEY] UPDATE не является строго атомарным для отдельных строк (ни для MyISAM, ни для InnoDB), но он будет атомарным в отношении ошибок.

Какая разница? Ну, это иллюстрирует потенциальную проблему в предположении строгой атомарности:

CREATE TABLE `updateTest` (
  `bar` INT(11) NOT NULL,
  `foo` INT(11) NOT NULL,
  `baz` INT(11) NOT NULL,
  `boom` INT(11) NOT NULL,
  PRIMARY KEY (`bar`)
)
COMMENT='Testing'
ENGINE=MyISAM;

INSERT INTO `updateTest` (`bar`, `foo`, `baz`, `boom`) VALUES (47, 1, 450, 2);

INSERT
    `updateTest`
    (`bar`, `foo`, `baz`, `boom`)
VALUES
    (47, 0, 400, 5)
ON DUPLICATE KEY UPDATE
    `foo` = IF(`foo` = 1, VALUES(`foo`), `foo`),
    `baz` = IF(`foo` = 1, VALUES(`baz`), `baz`),
    `boom` = IF(`foo` = 1, VALUES(`boom`), `boom`);

(47, 1, 450, 2) превратится в (47, 0, 450, 2), а не в (47, 0, 400, 5). Если вы предполагаете строгую атомарность (что не означает, что вы должны это делать; вы можете предпочесть такое поведение), этого не должно происходить — foo определенно не должно изменяться до тех пор, пока значения других столбцов не станут даже оценивается. foo должен меняться вместе с другими столбцами — все или ничего.

Если я говорю атомарный в отношении ошибок, я имею в виду, что если вы удалите условие IF() в приведенном выше примере, которое подчеркивает более строгую ситуацию, например эту...

INSERT INTO `updateTest` (`bar`, `foo`, `baz`, `boom`) VALUES (48, 1, 450, 2);

INSERT
    `updateTest`
    (`bar`, `foo`, `baz`, `boom`)
VALUES
    (48, 0, 400, 5)
ON DUPLICATE KEY UPDATE
    `foo` = VALUES(`foo`),
    `baz` = VALUES(`baz`),
    `boom` = VALUES(`boom`);

... вы всегда будете либо в конечном итоге с (48, 1, 450, 2) или (48, 0, 400, 5) после того, как ваше выражение завершится/сбой, и не какое-то промежуточное состояние, например (48, 0, 450, 2).

То же самое верно и для поведения UPDATE, но еще меньше причин жонглировать операторами IF(), так как вы можете просто поместить свои условные операторы в предложение WHERE.

В заключение: вне крайних случаев у вас есть атомарность для операторов с одной строкой, даже при использовании MyISAM. Дополнительную информацию см. в ответе Йоханнеса Х..

person pinkgothic    schedule 07.10.2014

Если механизм хранения таблиц InnoDB, да , операция определенно атомарна и частичная вставка невозможна. Я считаю, что это не так с MyISAM, движком по умолчанию, поскольку он не совместим с ACID и не поддерживает транзакции.

person TypeIA    schedule 05.02.2014
comment
MyISAM является атомарным, однако не обязательно последовательным, надежным или изолированным. Смотрите мой ответ. - person Johannes H.; 05.02.2014
comment
MyISAM не является атомарным, поскольку этот термин обычно применяется к системам баз данных. - person Marcus Adams; 05.02.2014
comment
@MarcusAdams Понимаю вашу точку зрения. Согласен, что базы данных MyISAM должны реализовывать «атомарные операции» как схему целостности. Это больше похоже на атомарность в том, как она используется вне терминологии СУБД. - person Johannes H.; 05.02.2014

Одиночные заявления, такие как это. Если вам нужно несколько вызовов для атомарного действия, вы можете использовать транзакции в большинстве реляционных баз данных.

person krowe    schedule 05.02.2014
comment
Поскольку речь идет конкретно о MySQL, это означает, что нужно использовать таблицы INNODB, поскольку MyIsam не поддерживает транзакции. - person Johannes H.; 05.02.2014
comment
Я бы сказал, что если вы задаете этот вопрос, вы должны использовать InnoDB. Если целостность данных имеет первостепенное значение, то InnoDB почти всегда лучше. - person krowe; 05.02.2014
comment
Полностью согласен с вами в этом вопросе, хотя ОП, Эми, не знаю. В дополнение к этому, поскольку мы говорим об огромном количестве данных (согласно OP), скорость может быть проблемой, хотя для MyISAM есть смысл. - person Johannes H.; 06.02.2014