mysql創建表的sql語句,sql怎么讀_mysql由于快照讀,造成數據混亂,該如何解決

 2023-10-08 阅读 24 评论 0

摘要:先看看問題場景某些業務需要更新某一個表的多個字段,很可能更新的結果跟理想值不一致。簡單來講就是執行類似下面的sql會出什么結果?update test set a = a+1,b=a+1 where id =2mysql創建表的sql語句、我們來模擬一下上面的sql環境,
3d11db52c4ee8974df673c1e2479e648.png

先看看問題場景

某些業務需要更新某一個表的多個字段,很可能更新的結果跟理想值不一致。簡單來講就是執行類似下面的sql會出什么結果?

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

mysql創建表的sql語句、我們來模擬一下上面的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)
efa94d7132936f72baf9bf8b3fb961fd.png

mysql 閃回。進行修改多個字段

update test set a = a+1,b=a+1 where id =2
8e35f809968e1dbeec76e4d240778339.png

修改的條件是id=2,為啥修改的結果是(2,21,22),不應該是(2,21,21)嗎?是不是很多人以為修改的結果是(2,21,21),是不是感覺數據是亂的,如果數據少,改回去還算省事,關鍵數據量很多,改的工作量就大了,還容易出錯。

原因分析

sql和mysql學哪個,因為 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 列暫存在一個臨時變量里

select?a?into?@a?from?test where?a=2;

再執行修改

update?test?set?a=@a+1,b=@a+1?where?a=@a;

結果就會是(2,21,21)了

總結一下

  • 快照讀

執行select的時候,innodb默認會執行快照讀,快照讀,也就是讀取快照的數據,數據雖然是一致的,但是數據是歷史數據。

快照讀:只是簡單的 select ,不包括 select … lock in share mode, select … for update

  • 當前讀

當你執行這幾個操作的時候默認會執行當前都會加鎖,也就是會讀取最新的記錄,也就是別的事務提交的數據你也可以看到。

update 執行當前讀,然后把返回的數據加鎖,之后執行update。

加鎖是防止別的事務在這個時候對這條記錄做什么,默認加的是排他鎖,也就是只允許讀,其他都不可以,這樣就可以保證數據不會出錯了。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/129293.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息