mysql update多字段时引发的一个问题
【1】问题描述
该问题已在mysql5.7 8.0 均已测试出现
create table test111(id int primary key auto_increment,a int ,b int);
update操作前
update操作后
同理(无论加不加主键索引,效果均如上图!)
我们发现,update多个列时,如果前一个列的值被改变,后一个列表达式中如果有引用到被改变列的值,那么是修改后的;
本来应该是 最终 a=15,b=30的,结果b=35了! 这并不是我们想要的结果;
【2】分析解决
(2.1)其他数据库会这样吗?不会
以mssql为例子
这里 a=a+2,b=b+a ,这里的 b=b+a 是 a=a+2 操作之前的数据
oracle
与上面一样,这里就不解释了
(2.2)为什么mysql会这样?
无论我测试8.0/5.7 版本,都会这样;
核心是因为 mysql 有 mvcc ??(参考文档中的文章是这样说的)
但我感觉,其实是因为
1.我感觉多列update
2.其实是拆成了 一个一个 update
(2.3)总结
1=》其他数据库:查出一版结果信息来后,锁定目标行数据加载到内存,然后引用次结果集上数据做计算
=》一次性计算出所有结果=》生成的新结果集记录到脏页;
=》注意这里的计算是整个多列update所有表达式都一起计算的;
2=》mysql数据库:查出一版结果信息来后,锁定目标行数据加载到内存,然后引用次结果集上数据做计算曹邹
=》会从左到右的执行 update 的 多列更新,先最左边这个,也就是说性质是类似拆成了多个update的形式;
如:
update test11 set a = a+5,b = b+a where id=1;
先执行 update test11 set a=a+5;
=》然后再 update test11 set b=b+a; 会重新来一遍当前读,所以这里的 a 是上一个 a=a+5 之后的结果值了;
【3】解决方案
(方法1)如果有依赖其他列操作的update,那么则一列一列update
(方法2)反向计算回去:
常规:update test11 set a = a+5,b = b+a where id=1;
反向计算回去:update test11 set a = a+5,b = b+a-5 where id=1;