5

在一个 Mysql 数据库中,每个表都基于启用了 Autocommit 的 InnoDB,带有子查询和/或连接的查询会是原子的吗?

例子:

  • INSERT INTO users SELECT (x,y,z) FROM users, comments WHERE users.id = comments.user_id; (加入)

  • UPDATE users, comments SET users.x = x1 WHERE users.age > 30;(加入)

  • UPDATE users, comments SET users.x = x1, comments.y = y1 WHERE users.age > 30;(加入)

  • UPDATE users, comments SET users.x = x1, comments.y = y1 WHERE users.id IN (SELECT id FROM users WHERE age > 30);(子查询)

4

4 回答 4

9

我理解您的问题,例如“每个查询本身都是原子操作吗?”。那么答案是“是”。其他两个答案是正确的,当他们说你所有的陈述加在一起不是原子的。

数据库中的原子性仅意味着全有或全无。这并不意味着数据的正确性。你的陈述成功与否。它与连接或子查询无关。一条语句就是一条语句,无论您的数据库是否必须在内存或磁盘上使用临时表。

事务只是告诉您的数据库将多个语句视为一个语句。当其中一条语句失败时,所有语句都会回滚。

这里一个重要的相关主题是隔离级别。你可能想了解这些。

编辑(回答评论):

这是正确的。只要它是一个有效的语句,并且没有发生电源故障或其他原因导致查询失败,它就会被完成。原子性本身只是保证语句是否正在执行。它保证完整性并且数据不会损坏(导致写入操作未完成或其他原因)。它不保证您数据的正确性。给定这样的查询,INSERT INTO foo SELECT MAX(id) + 1 FROM bar;您必须通过设置正确的隔离级别来确保您不会得到幻读或任何东西。

于 2013-10-18T08:32:04.297 回答
4

不,除非你START TRANSACTION像这样把它们包起来

START TRANSACTION;
   SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
   UPDATE table2 SET summary=@A WHERE type=1; 
COMMIT;

Mysql 手册中的示例

于 2013-10-18T08:17:31.550 回答
3

您的 sql 语句不会在 autocommit 开启的情况下自动执行。您需要启动事务才能关闭自动提交。见http://dev.mysql.com/doc/refman/5.0/en/commit.html

于 2013-10-18T08:14:01.773 回答
0

我不认为它是,我会解释你为什么。我对 MySQL 有一个非常奇怪的问题。

想象一下,您有一个名为“table1”的表,其中包含一条记录。f1 列的值为“A”。f2 列的值为“B”

Update table1 set f1 = CONCAT(f1,f2), f2 = 'C';

正如预期的那样,f1 的最终值是“AB”。

但是如果你改变顺序:

Update table1 set f2 = 'C', f1 = CONCAT(f1,f2);

f1 的最终值为“AC”。即:先改变f2,再改变f1。

我的结论是更新操作显然是非原子的。f2 先改变。f1 在使用 f2 的更新值后发生了变化,而不是原来的值。

于 2017-12-14T23:36:06.013 回答