14.2.2.2 Consistent Nonlocking Reads
A consistent
read means that InnoDB
uses
multi-versioning to present to a query a snapshot of the database at a point in time. The query sees the changes made by transactions that committed before that point of time, and no changes made by later or uncommitted transactions. The exception to this
rule is that the query sees the changes made by earlier statements within the same transaction. This exception causes the following anomaly: If you update some rows in a table, a SELECT
sees
the latest version of the updated rows, but it might also see older versions of any rows. If other sessions simultaneously update the same table, the anomaly means that you might see the table in a state that never existed in the database.
If the transaction isolation
level is REPEATABLE
READ
(the default level), all consistent reads within the same transaction read the snapshot established by the first such read in that transaction. You can get a fresher snapshot for your queries by committing the current transaction
and after that issuing new queries.
With READ
COMMITTED
isolation level, each consistent read within a transaction sets and reads its own fresh snapshot
我們在可重複讀下做個實驗:
同時開啓兩個事務,打開兩個mysql連接,分別begin;
事務A: begin;
select count(*) from Account where user_id = 'a'; //此時查到一條記錄
事務B begin;
此時在事務B中:
update Account set user_id = 'p_1' where user_id = 'a';
此時在事務A中繼續執行相同條件查詢,結果和上一張圖片相同(B未提交,當然看不到了),之後,B中commit
我們再來A中按照user_id = 'a' 和user_id = 'p_1'兩種方式進行查詢。
從這裏可以看到,在A中,一致性非鎖定讀讀取的仍然是同一個快照版本,即舊的版本,此時存在新的版本,user_id 爲'p_1',這時候我們按照user_id=‘p_1’查不到數據,但是,在同一個事務中,我們不是select,而用update,就會查到數據,因爲此時沒有使用一致性非鎖定讀,select對應的是舊快照的版本,而update修改的確是最新的版本,我們繼續執行update
先確認下查不到數據
此時執行更新:
這是正如上面所說,update竟然是有數據的。