MySQL更新导致列值更改中途查询

时间:2017-08-03 17:28:10

标签: mysql sql atomicity

任何人都可以解释为什么会在MySQL中发生这种情况吗?

mysql> select * from test;
+----+---+---+
| id | a | b |
+----+---+---+
|  1 | 1 | 1 |
+----+---+---+
1 row in set

mysql> update test set a = a + 1, b = a + 1;
Query OK, 1 row affected
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from test;
+----+---+---+
| id | a | b |
+----+---+---+
|  1 | 2 | 3 |
+----+---+---+
1 row in set

mysql> 

架构:

CREATE TABLE `test` (
  `id` int(10) unsigned NOT NULL,
  `a` int(10) unsigned NOT NULL,
  `b` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3 个答案:

答案 0 :(得分:2)

据我所知,sql做了从左到右的评估。因此,如果您更新a中的值并使用a作为b的基础。新值将反映

SQL UPDATE order of evaluation

答案 1 :(得分:1)

这是预期的行为,according to the MySQL documentation

  

如果从表中访问要在表达式中更新的列,UPDATE将使用列的当前值。例如,以下语句将col1设置为比其当前值多一个:

     

UPDATE t1 SET col1 = col1 + 1;

     

以下语句中的第二个赋值将col2设置为当前(更新的)col1值,而不是原始col1值。结果是col1和col2具有相同的值。此行为与标准SQL不同。

     

UPDATE t1 SET col1 = col1 + 1, col2 = col1;

     

单表UPDATE分配通常从左到右进行评估。对于多表更新,无法保证以任何特定顺序执行分配。

但是,如果您想阻止它,并让查询使用原始值,请尝试在事务中运行它。

答案 2 :(得分:-1)

试试这个:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
update test set a = a + 1, b = a + 1;

可以更改隔离级别...... https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html