MySQL半一致性讀原理解析-從原始碼角度解析
1、什麼是半一致性讀
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.
就是發生在update語句中。在RC隔離級別或者innodb_locks_unsafe_for_binlog被設定為true,併發時,如果update的記錄發生鎖等待,那麼返回該記錄的prev 版本(在返回前會將鎖等待的這個lock從trx中刪除掉),到mysql層進行where判斷,是否滿足條件。如果滿足where條件,那麼再次進入innodb層,真正加鎖或者發生鎖等待。
這樣做的好處是:減少同一行記錄的鎖衝突及鎖等待;無併發衝突時,直接讀取最新版本加鎖,有衝突時,不加鎖,讀取prev版本不需要鎖等待。
缺點:非衝突序列話策略,對於binlog來說是不安全的。只能發生在RC隔離級別和innodb_lock_unsafe_for_binlog下。
2、原理
3、講解
1)半一致性讀需要mysql層和innodb層配合使用。
2)mysql_update函式中,預設都會呼叫try_semi_consistent_read在RC或innodb_lock_unsafe_for_binlog下加上試圖半一致性讀標籤:prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT。真正執行半一致性讀是由innodb層決定。
3)半一致性讀的條件:該記錄發生鎖等待;必須是全表掃描 && 該索引是二級索引
4)半一致性讀時,構建prev版本,然後呼叫函式lock_trx_handle_wait將鎖等待從trx中刪除。
5)返回prev rec前,會將置成半一致性讀標籤:prebuilt->row_read_type = ROW_READ_DID_SEMI_CONSISTENT
6)返回到mysql層,會進行where判斷。如果匹配,那麼會再次進入innodb層,由於prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT,此時不再走半一致性讀判斷的流程,直接進入加鎖或鎖等待。
5)這裡update有個最佳化:innodb層如果執行計劃是索引下推,那麼判斷where條件是否匹配會提前。若不匹配則提前呼叫函式row_unlock_for_mysql釋放聚集索引上的鎖
6)另外一個最佳化:返回mysql層後,判斷where不匹配,則會呼叫unlock_row函式釋放鎖。注:這裡update在innodb層沒有發生鎖衝突,成功加上了鎖。即沒有半一致性讀
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31493717/viewspace-2153163/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從原始碼的角度解析執行緒池執行原理原始碼執行緒
- 從ReentrantLock詳解AQS原理原始碼解析ReentrantLockAQS原始碼
- 從原始碼的角度解析Mybatis的會話機制原始碼MyBatis會話
- 從原始碼角度解析 Springboot 2.6.2 的啟動過程原始碼Spring Boot
- MySQL核心原始碼解讀-SQL解析一MySql原始碼
- 從原始碼角度來讀Handler原始碼
- MySQL核心原始碼解讀-SQL解析之解析器淺析MySql原始碼
- 從ReentrantLock角度解析AQSReentrantLockAQS
- 從原始碼角度分析 MyBatis 工作原理原始碼MyBatis
- EventBus原理與原始碼解析原始碼
- vuex 2.*原始碼解析—— 花半小時就可以讀懂vuex實現原理Vue原始碼
- 深入解析:從原始碼窺探MySQL優化器原始碼MySql優化
- TiCDC 原始碼閱讀(四)TiCDC Scheduler 工作原理解析原始碼
- 從規範的角度解析物件 — 原始值轉換物件
- ArrayList 從原始碼角度剖析底層原理原始碼
- 從原始碼角度解析執行緒池中頂層介面和抽象類原始碼執行緒抽象
- Java集合類,從原始碼解析底層實現原理Java原始碼
- Laravel 原始碼閱讀指南 -- Cookie 原始碼解析Laravel原始碼Cookie
- 從pytest原始碼的角度分析pytest工作原理原始碼
- 從原始碼解析 Swift 弱引用原始碼Swift
- 深入原始碼解析 tapable 實現原理原始碼
- CORS原理及@koa/cors原始碼解析CORS原始碼
- SpringBoot原始碼解析-@ConditionalOnXXX註解原理Spring Boot原始碼
- Netty原始碼解析 -- PoolChunk實現原理Netty原始碼
- Netty原始碼解析 -- PoolSubpage實現原理Netty原始碼
- Laravel核心解讀–Session原始碼解析LaravelSession原始碼
- Spring原始碼閱讀-IoC容器解析Spring原始碼
- 從原始碼角度談談AsyncTask的使用及其原理原始碼
- InnoDB MVCC實現原理及原始碼解析MVC原始碼
- Tomcat長輪詢原理與原始碼解析Tomcat原始碼
- mysql資料一致性解析MySql
- java8LinkedList原始碼閱讀解析Java原始碼
- Spring 原始碼閱讀之標籤解析Spring原始碼
- HashMap原始碼解析和設計解讀HashMap原始碼
- Java Timer原始碼解析(定時器原始碼解析)Java原始碼定時器
- 【原始碼解析】- ArrayList原始碼解析,絕對詳細原始碼
- [原始碼解析] 深度學習分散式訓練框架 horovod (2) --- 從使用者角度切入原始碼深度學習分散式框架
- 從Chrome原始碼看DNS解析過程Chrome原始碼DNS