1、快照讀
快照讀是基於 MVCC 和 undo log 來實現的,適用於簡單 select 語句。
讀已提交:一個事務內操作一條數據,可以查詢到另一個已提交事務操作同一條數據的最新值。(Oracle 默認隔離級別)
可重復讀:每個事務只關注自己事務開始查詢到的數據值,無論事務查詢同一條數據多少次,該數據改了多少次,都只查詢到事務開始之前的數據值。(MySQL 默認隔離級別)
而所謂 MVCC 並發版本控制,是靠 readView (事務視圖) 來實現的。多個 readView 組成 undo log(回滾日志)。
每一個 sql 查詢某條數據時,都是查詢最新 readView 的該條數據的值。
ReadView:(查詢同一條數據,因為 readView 也是針對同一條數據生成的視圖)
讀已提交:是事務中的每個 sql 語句生成一個 readView。那就是一個事務內多條 sql 語句,會生成多個 readView。而每條 sql 執行時,都是查詢最新 readView 的值。
假如事務 A 有2個查詢 sql 語句,在第一個查詢 sql 生成一個 readView(事務視圖 id = n),事務 B 對該數據做了操作,那么就會生成新的 readView(事務視圖 id = n + 1),第二個查詢 sql 語句獲取該條數據時,就會去 readView(事務視圖 id = n + 1)查詢數據。
可重復讀:是在事務開始的時候生成一個 readView。所以一個事務內的多條查詢 sql ,查詢同一條數據時,讀取到的 readView 都是同一個,那么查詢某條數據的值,也是同一個值。
例如事務A開始查詢主鍵 id = 1 的行數據的列 age = 10,不管其他事務是否對該 age 做改變,當前事務的多條查詢 sql 語句,查詢 age 的值一直都是 age = 10。
2、當前讀
當前讀是基於 臨鍵鎖(行鎖 + 間歇鎖)來實現的,適用於 insert,update,delete, select ... for update, select ... lock in share mode 語句,以及加鎖了的 select 語句。
當前讀:
更新數據時,都是先讀后寫,而這個讀,就是當前讀。讀取數據時,讀取該條數據的已經提交的最新的事務,生成的 readView。
例如事務 A 有2個 sql 語句,事務開始時生成 readView(id = n),第一個 sql 操作一條數據時讀當前的 readView(id = n) 。此時開始事務B生成 readView(id = n + 1),並且對該條數據做了操作(非簡單 select 操作)。事務A的第2個 sql 語句當前讀該數據時,就會讀取該數據的最新事務視圖 readView (id =n + 1) 的值。
而假如事務A的第二個 sql 語句操作數據時,事務B還未提交(非簡單 select 操作),那么該條數據此時被事務B的寫鎖鎖住。事務A的第二個 sql 語句操作數據(非簡單 select 操作),那么也要獲取該條數據的鎖。而此時鎖被事務B持有,事務A就會阻塞,等待事務B釋放鎖。