事務並行可能出現的問題
事務的4個隔離級別,以及解決的問題
四個隔離級別和可以解決的問題是SQL專門規定的,但是在Innodb引擎下,在可重複讀的隔離級別的下就可以直接解決幻讀的問題。
我們可以在啟動時指定系統引數修改系統預設的隔離級別,預設為可重複讀。
mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set, 1 warning (0.00 sec)
我們在前面就講過了undo紀錄檔,對於每次進行增刪改就會產生undo紀錄檔,這時每個資料行的roll_pointer就會指向一個undo連結串列,我們就稱其為版本鏈。我們在提一嘴,因為insert的undo紀錄檔在提交後是沒有用的,所以在事務提交後insert的undo就會被釋放。
可以到前面的文章瞭解一下undo紀錄檔。大概知道undo紀錄檔的型別和產生的過程就OK了感覺怎麼儲存undo紀錄檔的那一部分講得雲裡霧裡https://www.cnblogs.com/duizhangz/p/16333565.html
為什麼沒用?因為插入並不維護舊值,只是表明一個插入,並不需要儲存什麼資訊。所以在事務提交時直接釋放掉。因為事務在回滾時需要由一條insert語句型別的undo進行回滾。
這就是上面倆事務生成的版本鏈。
undo連結串列頭儲存的就是最新事務更新的記錄資訊。
對於不同的事務隔離級別,我們可以讀取的記錄資料是不一樣的。
對於未提交讀的隔離級別來說,我們可以直接讀到資料的最新版本。
對於提交讀的隔離級別來說,我們需要可以讀到的就是已經提交的事務的修改資料。
對於可重複讀的隔離級別來說,我們需要可以讀到在事務開啟前已經提交的事務的資料。
對於序列讀的隔離節別來說,Innodb採用加鎖的方式來保證序列讀。
對於中間兩個隔離級別,就需要ReadView這個結構來實現MVCC。以下是ReadView的結構
有了ReadView這個結構,我們在就可以對事務進行控制。
當前情況在版本鏈中從頭到尾遍歷,直到獲得到資料。
上面提到的提交讀和可重複讀,因為是兩個隔離級別有區別的,兩個隔離級別的實現只要在ReadView的時機上進行把控,就可以實現。
仔細品一品,一下就可以恍然大悟。
這個MVCC只會在我們使用普通select查詢才會生效。