【问题标题】:Is join insert/update on MySQL an atomic operation?MySQL 上的 join insert/update 是原子操作吗?
【发布时间】:2013-10-18 08:07:25
【问题描述】:

在一个 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);(子查询)

【问题讨论】:

    标签: mysql sql concurrency locking atomic


    【解决方案1】:

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

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

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

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

    编辑(回答评论):

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

    【讨论】:

    • 但是原子性并不意味着没有其他查询会干扰查询执行?在像“INSERT INTO users SELECT (x,y,z) FROM users, cmets WHERE users.id = cmets.user_id AND condition”这样的查询中,您被授予如果满足 where 条件,则更新将正确执行后。对不对?
    • @DamianoBarbati 更新了我的答案。
    • 同意。我的假设是基于sql statements 的问题,即从另一个表中复制一行,然后更改该行中的数据。
    【解决方案2】:

    没有。除非您像这样将它们包装在START TRANSACTION

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

    来自Mysql manual的示例

    【讨论】:

    • 他在一个语句中谈论原子性。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      我不认为是这样,我会解释为什么。我在使用 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 先改变。使用 f2 的更新值后,f1 发生了变化,而不是原来的值。

      【讨论】:

      • 这没有意义。就像事务一样,原子性意味着全有或全无,序列保持原样。
      • 如果 MySQL 使用写锁更新,当前语句可以从 MySQL 读取或写入。它拥有一个可以读取的写锁。
      猜你喜欢
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 2013-10-25
      • 2015-02-17
      • 2018-01-06
      • 1970-01-01
      相关资源
      最近更新 更多