A type of read operation used for UPDATE statements, that is a combination of read committed and consistent read. When an UPDATE statement examines a row that is already locked, InnoDB returns the latest committed version to MySQL so that MySQL can determine whether the row matches the WHERE condition of the UPDATE. If the row matches (must be updated), MySQL reads the row again, and this time InnoDB either locks it or waits for a lock on it. This type of read operation can only happen when the transaction has the read committed isolation level, or when the innodb_locks_unsafe_for_binlog option is enabled.
簡單來說,semi-consistent read是read committed與consistent read兩者的結合。一個update語句,如果讀到一行已經加鎖的記錄,此時InnoDB返回記錄最近提交的版本,由MySQL上層判斷此版本是否滿足update的where條件。若滿足,則MySQL會重新發起一次讀操作,此時會讀取行的最新版本(並加鎖)。
semi-consistent read只會發生在read committed隔離級別下,或者是參數innodb_locks_unsafe_for_binlog=ON。
create table semi(a int not null); insert into semi values (1),(2),(3),(4),(5),(6),(7);
1. read commit 級別演示: 讀取不到滿足條件的數據
session 2不需要等待session 1,雖然session 1的更新后項滿足session 2的條件,但是由於session 2進行了semi-consistent read,讀取到的記錄的為(1-7),不滿足session 2的更新where條件,因此session 2直接返回。
2. repeatable read 演示 :等待滿足條件的數據
3. repeatable read 演示: 不滿足條件,直接釋放數據
session 1在session 2開始前已經提交,session 2可以進行semi-consistent read。並且讀到的都是session 1的更新后項,完成加鎖。但是由於更新后項均不滿足session 2的where條件,session 2會釋放所有行上的鎖(由MySQL Server層判斷並釋放行鎖)。
此時,session 1再次執行select * from t1 lock in share mode語句,直接成功。因為session 2已經將所有的行鎖提前釋放。
優點
- 減少了更新同一行記錄時的沖突,減少鎖等待
-
可以提前放鎖,進一步減少並發沖突概率
缺點
-
非沖突串行化策略,因此對於binlog來說,是不安全的
兩條語句,根據執行順序與提交順序的不同,通過binlog復制到備庫后的結果也會不同。不是完全的沖突串行化結果。
因此只能在事務的隔離級別為read committed(或以下),或者設置了innodb_locks_unsafe_for_binlog=ON的情況下才能夠使用。
出處:
何登成:MySQL+InnoDB semi-consitent read原理及實現分析