今天朋友问mysql的update set的内容是否有顺序问题
我想,数据库更新应该是拿出该数据的快照,根据快照数据做更新,本着这个思路,我们来看看那么mysql是如何工作的,同时我们还好奇的测试了sql server和oracle。
业务语句
我们调整了set后面的顺序
可以看到va_raito是不同的,也就是说mysql的update是有顺序的
我们找到了mysql的官方手册,里面也有详细的说明,跟我们想象的不同
借用一个开发的思路:这就好像程序里面评估表达式的值一样吧,从左往右进行。看似很说的通哈,但是不知道DBA们是否能接受,反正我是不太接受:)
DBA更多的考虑数据ACID,那么我们来看看,是否是因为事物隔离级别导致
当前的事物隔离级别是:REPEATABLE-READ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| mysql> SELECT @@GLOBAL.tx_isolation; +-----------------------+ | @@GLOBAL.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ 1 row in set (0.00 sec) mysql> create table t3 (a int ,b int); Query OK, 0 rows affected (0.00 sec) mysql> insert into t3 values (1,2); Query OK, 1 row affected (0.01 sec) mysql> update t3 set a=a+10,b=a; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t3; +------+------+ | a | b | +------+------+ | 11 | 11 | +------+------+ 1 row in set (0.00 sec)
|
修改为:READ-UNCOMMITTED
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| mysql> SELECT @@GLOBAL.tx_isolation; +-----------------------+ | @@GLOBAL.tx_isolation | +-----------------------+ | READ-UNCOMMITTED | +-----------------------+ 1 row in set (0.00 sec) mysql> create table t3 (a int ,b int); Query OK, 0 rows affected (0.02 sec) mysql> insert into t3 values (1,2); Query OK, 1 row affected (0.01 sec) mysql> update t3 set a=a+10,b=a; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t3; +------+------+ | a | b | +------+------+ | 11 | 11 | +------+------+ 1 row in set (0.00 sec)
|
通过以上测试我们可以看到,这个问题属于update语法问题,无论是从update官方手册说明,还是事物隔离级别测试,都表明update set顺序不受其他配置影响。
那么,我们来看看sql server和oracle
sql server
oracle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| SQL> create table t1(a int ,b int); Table created. SQL> insert into t1 values(1,2); 1 row created. SQL> commit; Commit complete. SQL> update t1 set a=a+10,b=a; 1 row updated. SQL> select * from t1; A B ---------- ---------- 11 1
|
两个商业软件和我们想的一致,唯有mysql产生了幻读,所以我们可以说它是一个小坑,也可以说它是一个讨巧。开发用好了会很方便,用不好数据就改错了,小心为上。