本文介紹了可重復(fù)讀取隔離級別SELECT VS UPDATE…WHERE的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習吧!
問題描述
也許你可以在這里為我解釋一些事情:
DB=MySQL 5.7
存儲引擎:InnoDB
隔離級別:可重復(fù)讀取
下表:
---------------
| MyTable |
---------------
| PK | Concur |
---------------
| 3 | 2 |
---------------
此時我沒有正在進行的事務(wù),我選擇此記錄,如下所示
SELECT * FROM MyTable WHERE PK = 3
并將結(jié)果存儲在我的程序中。
我現(xiàn)在啟動一個數(shù)據(jù)庫事務(wù)。
事務(wù)開始后,外部進程將PK
=3的記錄的Concur
從2遞增到3。
我尚未再次從事務(wù)內(nèi)的該表中讀取。
我從我的事務(wù)內(nèi)部發(fā)出以下查詢:
UPDATE MyTable SET Concur = 3 WHERE PK = 3 AND Concur = 2
這將通過0 records affected
成功。很明顯,它會根據(jù)我的事務(wù)開始后更改的數(shù)據(jù)進行評估。
仍在事務(wù)中,我隨后查詢:
SELECT * FROM MyTable WHERE PK = 3
它將向我返回PK = 3 and Concur = 2
的記錄,這些值是事務(wù)之前的值。
為什么SELECT
和UPDATE ... WHERE
的行為不同,我缺少什么?
我認為UPDATE ... WHERE
語句要么直接失敗,而不是在0條記錄受到影響的情況下成功,要么在那里成功,但有1條記錄受到影響,然后在隨后的COMMIT
處失敗,但不是這種混合和匹配。
這里有什么見解嗎?
推薦答案
https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html
一致讀取意味著InnoDB使用多版本控制向查詢呈現(xiàn)某個時間點的數(shù)據(jù)庫快照。查詢會看到在該時間點之前提交的事務(wù)所做的更改,而不會看到后來或未提交的事務(wù)所做的更改。此規(guī)則的例外情況是,查詢會看到同一事務(wù)中較早的語句所做的更改。此異常會導(dǎo)致以下異常:如果更新表中的某些行,SELECT會看到更新的行的最新版本,但也可能會看到任何行的較舊版本。如果其他會話同時更新同一個表,則異常情況意味著您可能會看到該表處于數(shù)據(jù)庫中不存在的狀態(tài)。
重要的條件是,如果您更改了行,您的一致讀取將被”刷新”,因此它包括您剛剛所做的更改。
但如果您更新,它始終是行的最新版本,而不是事務(wù)的一致讀取可以查看的版本。因此,如果另一個事務(wù)已經(jīng)進行了該更改,則您的更新可能不會產(chǎn)生任何凈效果。這就是您觀察到的情況。
因此,您的事務(wù)發(fā)出了更新,但未更改行。
這可能不是您希望InnoDB的行為方式,但它確實是這樣的。
這篇關(guān)于可重復(fù)讀取隔離級別SELECT VS UPDATE…WHERE的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,