1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > sql怎么读_mysql由于快照读 造成数据混乱 该如何解决

sql怎么读_mysql由于快照读 造成数据混乱 该如何解决

时间:2023-09-05 21:22:00

相关推荐

sql怎么读_mysql由于快照读 造成数据混乱 该如何解决

先看看问题场景

某些业务需要更新某一个表的多个字段,很可能更新的结果跟理想值不一致。简单来讲就是执行类似下面的sql会出什么结果?

update test set a = a+1,b=a+1 where id =2

我们来模拟一下上面的sql环境,我们创建一个test表,并使用innodb存储引擎。

create table test (id int,a int,b int,primary key(id));

增加三行数据

insert into test values (1,10,100),(2,20,200),(3,30,300)

进行修改多个字段

update test set a = a+1,b=a+1 where id =2

修改的条件是id=2,为啥修改的结果是(2,21,22),不应该是(2,21,21)吗?是不是很多人以为修改的结果是(2,21,21),是不是感觉数据是乱的,如果数据少,改回去还算省事,关键数据量很多,改的工作量就大了,还容易出错。

原因分析

因为 update 是当前读,读取的是记录数据的最新版本,

update test set a = a+1,b=a+1 where id =2

update a=a+1 因为要做当前读 现在a =20 +1 后 a=21 ,保证最新值,再做 b=a+1

也需要读到a值的最新的值 还要加锁, 现在a的值已经变成21, 再加1就变成22,

那么如果我想按照我们的理想值更新出结果,那要怎么做呢?

问题解决

可以把 a 列暂存在一个临时变量里

selectainto@afromtest wherea=2;

再执行修改

updatetestseta=@a+1,b=@a+1wherea=@a;

结果就会是(2,21,21)了

总结一下

快照读

执行select的时候,innodb默认会执行快照读,快照读,也就是读取快照的数据,数据虽然是一致的,但是数据是历史数据。

快照读:只是简单的 select ,不包括 select … lock in share mode, select … for update

当前读

当你执行这几个操作的时候默认会执行当前都会加锁,也就是会读取最新的记录,也就是别的事务提交的数据你也可以看到。

update 执行当前读,然后把返回的数据加锁,之后执行update。

加锁是防止别的事务在这个时候对这条记录做什么,默认加的是排他锁,也就是只允许读,其他都不可以,这样就可以保证数据不会出错了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。