mysql是否在Single查询中多次插入原子?

pil*_*ght 9 mysql sql insert atomic sql-update

我在做一个多刀片查询:

INSERT INTO table (c1, c2) VALUES (1,2),
                                  (2,3),
                                  (3,4),......
         ON DUPLICATE KEY UPDATE c2 = VALUES(c2)
Run Code Online (Sandbox Code Playgroud)

现在假设在查询中指定了超过数万个VALUES(因此省略号)....

有没有一种情况,VALUES的某些部分设法在数据库中插入/更新,但其余部分可能由于某种db错误/故障/内存耗尽等而未插入/更新?

mysql查询是ALL还是Nothing?

对于每个执行的mysql查询,是否可以顺利插入/更新查询中指定的所有值,或者不会插入/更新任何值?

Joh*_* H. 14

ACID (原子性,一致性,隔离性,持久性)属性用于描述数据库中的此类行为.只有在我们处理并发修改时,原子性才是重要的.为确保一致性,必须达到一定程度的隔离.但是,运行的隔离多个事务越多,DBMS通常具有的性能就越低.所以有一个所谓的" 隔离级别 ",它说明了DBMS中可能发生的错误,哪些不可能.

现在,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).但请注意,这并不保证在一次操作中读取和写入之间的数据不会更改 - DBMS术语中的原子性仅表示操作已完全完成或完全跳过.它不保证隔离,一致性或耐用性.

  • 请问downvote是干什么用的?我没有看到任何评论或编辑建议... (2认同)
  • ...那里有恶意的downvoters.我认为这是一个很好的答案.+1. (2认同)
  • @JohannesH.这可能是因为MySQL链接指向德语docs =)修复它. (2认同)

pin*_*hic 5

“是否有可能因为某种数据库错误/故障/内存耗尽等原因,VALUES 的某些部分设法插入/更新到数据库中,但其余部分没有插入/更新? ”

迟到的答案,但也许很有趣:对于单行(既不是 for也不是 for )[ON DUPLICATE KEY] UPDATE不是严格原子的,但它在错误方面是原子的。MyISAMInnoDB

有什么不同?好吧,这说明了假设严格原子性的潜在问题:

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`);
Run Code Online (Sandbox Code Playgroud)

(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`);
Run Code Online (Sandbox Code Playgroud)

...你将永远要么结了(48, 1, 450, 2) (48, 0, 400, 5)你的发言结束后/坠毁,而不是一些中间状态一样(48, 0, 450, 2)

的行为也是如此UPDATE,但没有理由在IF()那里处理语句,因为您可以将条件WHERE语句放入您的子句中。

结论:在边缘情况之外,您确实具有单行语句的原子性,即使使用MyISAM. 有关更多信息,请参阅Johannes H. 的回答