"Може ли някога да има случай, в който някои части от VALUES да са успели да бъдат вмъкнати/актуализирани в базата данни, но останалите не са били вмъкнати/актуализирани вероятно поради някаква db грешка/неуспех/изпълнение на паметта- извън и т.н.?"
Късен отговор, но може би интересен: [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
. Вижте отговора на Johannes H. за допълнителна информация.
person
pinkgothic
schedule
07.10.2014
insert
трябва да бъде атомарно във всяка ACID-съвместима база данни. - person Gordon Linoff   schedule 05.02.2014