在MySQL上加入insert / update是一个原子操作吗?

时间:2013-10-18 08:07:25

标签: mysql sql concurrency locking atomicity

在一个Mysql数据库中,每个表基于启用了自动提交的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 个答案:

答案 0 :(得分:8)

我理解你的问题是“每个查询本身都是一个原子操作吗?”。然后答案是肯定的。另外两个答案是正确的,当他们说你所有的陈述都不是原子的时候。

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

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

这里一个重要的相关主题是isolation level。您可能想了解这些内容。

编辑(回答评论):

没错。只要它是有效的声明并且没有发生电源故障或查询可能失败的其他原因,它就完成了。原子性本身只保证声明是否正在完成。它保证了完整性并且数据没有损坏(导致写入操作没有完成或者某些事情)。 它并不能保证数据的正确性。鉴于像INSERT INTO foo SELECT MAX(id) + 1 FROM bar;之类的查询,您必须确保通过设置正确的隔离级别,而不是得到幻读或任何东西。

答案 1 :(得分:4)

没有。除非你把它们包裹在这样的START TRANSACTION

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

来自Mysql manual

的示例

答案 2 :(得分:3)

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

答案 3 :(得分: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的更新值后更改,而不是原始值。