gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

一文聊聊Mysql鎖的內部實現機制

本篇文章帶大家聊聊Mysql鎖的內部實現機制,希望對大家有所幫助。

一文聊聊Mysql鎖的內部實現機制

千萬級數據并發如何處理?進入學習

注:所列舉代碼皆出自Mysql-5.6

雖然現在關系型數據庫越來越相似,但其背后的實現機制可能大相徑庭。實際使用方面,因為SQL語法規范的存在使得我們熟悉多種關系型數據庫并非難事,但是有多少種數據庫可能就有多少種鎖的實現方法。

Microsoft Sql Server2005之前只提供頁鎖,直到2005版本才開始支持樂觀并發、悲觀并發,樂觀模式下允許實現行級別鎖,在Sql Server的設計中鎖是一種稀缺資源,鎖的數量越多,開銷就越大,為了避免因為鎖的數量快速攀升導致性能斷崖式下跌,其支持一種稱為鎖升級的機制,一旦行鎖升級為頁鎖,并發性能就又回到原點。

事實上,即使在同一個數據庫,不同的執行引擎對鎖這一功能的詮釋依然是百家爭鳴。對于MyISAM而言僅僅支持表鎖,并發讀取尚可,并發修改可就捉襟見肘了。Innodb則和Oracle非常相似,提供非鎖定一致性讀取、行鎖支持,與Sql Server明顯不同的是隨著鎖總數的上升,Innodb僅僅只需要付出一點點代價。

行鎖結構

Innodb支持行鎖,且對于鎖的描述并不會存在特別大的開銷。因此不需要鎖升級這一機制作為大量鎖導致性能下降之后的搶救措施。

摘自lock0priv.h文件,Innodb對于行鎖的定義如下:

/** Record lock for a page */ struct lock_rec_t {     /* space id */     ulint  space;	          /* page number */     ulint  page_no;          /**      * number of bits in the lock bitmap;       * NOTE: the lock bitmap is placed immediately after the lock struct       */     ulint  n_bits;			 };

不難看出雖然并發控制可以細化到行級別,但是鎖以頁的粒度組織管理。Innodb的設計中通過space id、page number兩個必要條件就可以確定唯一一個數據頁,n_bits表示描述該頁行鎖信息需要多少bit位。

同一數據頁中每條記錄都分配唯一的連續的遞增序號:heap_no,若要知道某一行記錄是否上鎖,則只需要判斷位圖heap_no位置的數字是否為一即可。由于lock bitmap根據數據頁的記錄數量進行內存空間分配的,因此沒有顯式定義,且該頁記錄可能還會繼續增加,因此預留了LOCK_PAGE_BITMAP_MARGIN大小的空間。

/**   * Safety margin when creating a new record lock: this many extra records  * can be inserted to the page without need to create a lock with   * a bigger bitmap  */ #define LOCK_PAGE_BITMAP_MARGIN	 64

假設space id = 20,page number = 100的數據頁目前有160條記錄,heap_no為2、3、4的記錄已經被鎖,則對應的lock_rec_t結構與數據頁應該被這樣刻畫:

一文聊聊Mysql鎖的內部實現機制

注:

  • 內存中的lock bitmap應該是線性分布的,圖中所示二維結構是為了方便描述
  • bitmap與lock_rec_t結構是一塊連續內存,圖中引用關系也是繪圖需要

可以看到該頁對應的bitmap第二三四位置全部置一,描述一個數據頁行鎖所消耗內存從感官上相當有限,那具體占用多少呢?我們可以計算一下:
160 / 8 + 8 + 1 = 29byte。

  • 160條記錄對應160bit
  • +8是因為需要預留出64bit
  • +1是因為源碼中還預留了1字節

這里還額外+1,應該是為了避免因為整除導致的結果數值偏小的問題。假如是161條記錄如果不+1則計算出來的20byte不夠描述所有記錄的鎖信息(不動用預留位)。

摘自lock0priv.h文件:

/* lock_rec_create函數代碼片段 */ n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN; n_bytes = 1 + n_bits / 8;  /* 注意這里是分配的連續內存 */ lock = static_cast<lock_t*>(     mem_heap_alloc(trx->lock.lock_heap, sizeof(lock_t) + n_bytes) );   /**  * Gets the number of records in the heap.  * @return number of user records   */ UNIV_INLINE ulint page_dir_get_n_heap(const page_t* page)	 {     return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff); }

表鎖結構

Innodb還支持表鎖,表鎖可分為兩大類:意向鎖,自增鎖其數據結構定義如下:

摘自lock0priv.h文件

struct lock_table_t {     /* database table in dictionary cache */     dict_table_t*  table;          /* list of locks on the same table */     UT_LIST_NODE_T(lock_t)  locks; };

摘自ut0lst.h文件

struct ut_list_node {     /* pointer to the previous node, NULL if start of list */     TYPE*  prev;          /* pointer to next node, NULL if end of list */     TYPE*  next; };   #define UT_LIST_NODE_T(TYPE)  ut_list_node<TYPE>

事務中鎖的描述

上述lock_rec_t、lock_table_t結構只是單獨的定義,鎖產生于事務之中,因此每個事務對應的行鎖、表鎖會有一個相應的鎖的結構,其定義如下:

摘自lock0priv.h文件

/** Lock struct; protected by lock_sys->mutex */ struct lock_t {     /* transaction owning the lock */     trx_t*  trx;          /* list of the locks of the transaction */     UT_LIST_NODE_T(lock_t)  trx_locks;	          /**       * lock type, mode, LOCK_GAP or LOCK_REC_NOT_GAP,      * LOCK_INSERT_INTENTION, wait flag, ORed       */     ulint  type_mode;          /* hash chain node for a record lock */     hash_node_t  hash;	          /*!< index for a record lock */     dict_index_t*  index;          /* lock details */     union {         /* table lock */         lock_table_t  tab_lock;                  /* record lock */         lock_rec_t  rec_lock;     } un_member; };

lock_t是根據每個事務每個頁(或表)來定義的,但是一個事務往往涉及到多個頁,因此需要鏈表trx_locks串聯起一個事務相關的所有鎖信息。除了需要根據事務查詢到所有鎖信息,實際場景還要求系統必須能夠快速高效的檢測出某個行記錄是否已經上鎖。因此必須有一個全局變量支持對行記錄進行鎖信息的查詢。Innodb選擇了哈希表,其定義如下:

摘自lock0lock.h文件

/** The lock system struct */ struct lock_sys_t {     /* Mutex protecting the locks */     ib_mutex_t  mutex;		          /* 就是這里: hash table of the record locks */     hash_table_t*  rec_hash;	          /* Mutex protecting the next two fields */     ib_mutex_t  wait_mutex;          /**       * Array  of user threads suspended while waiting forlocks within InnoDB,      * protected by the lock_sys->wait_mutex       */     srv_slot_t*  waiting_threads;          /*      * highest slot ever used in the waiting_threads array,      * protected by lock_sys->wait_mutex       */     srv_slot_t*  last_slot;          /**       * TRUE if rollback of all recovered transactions is complete.       * Protected by lock_sys->mutex       */     ibool  rollback_complete; 		     /* Max wait time */     ulint  n_lock_max_wait_time;      /**      * Set to the event that is created in the lock wait monitor thread.      * A value of 0 means the thread is not active      */     os_event_t	timeout_event;		      /* True if the timeout thread is running */     bool  timeout_thread_active; };

函數lock_sys_create在database start之際負責初始化lock_sys_t結構。rec_hash的hash slot數量由srv_lock_table_size變量決定。rec_hash哈希表的key值通過頁的space id,page number計算得出。

摘自lock0lock.icut0rnd.ic 文件

/**  * Calculates the fold value of a page file address: used in inserting or  * searching for a lock in the hash table.  *  * @return folded value   */ UNIV_INLINE ulint lock_rec_fold(ulint space, ulint page_no) {     return(ut_fold_ulint_pair(space, page_no)); }   /**  * Folds a pair of ulints.  *  * @return folded value   */ UNIV_INLINE ulint ut_fold_ulint_pair(ulint n1, ulint n2) {     return (         (             (((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1)             ^ UT_HASH_RANDOM_MASK         )          + n2     ); }

這將意味著無法提供一個手段使得我們可以直接得知某一行是否上鎖。而是應該先通過其所在的頁得到space id、page number通過lock_rec_fold函數得出key值而后經過hash查詢得到lock_rec_t,而后根據heap_no掃描bit map,最終確定鎖信息。lock_rec_get_first函數實現了上述邏輯:

這里返回的其實是lock_t對象,摘自lock0lock.cc文件

/**  * Gets the first explicit lock request on a record.  *  * @param block   : block containing the record   * @param heap_no : heap number of the record   *  * @return first lock, NULL if none exists   */ UNIV_INLINE lock_t* lock_rec_get_first(const buf_block_t* block, ulint heap_no) {     lock_t*  lock;      ut_ad(lock_mutex_own());      for (lock = lock_rec_get_first_on_page(block); lock;          lock = lock_rec_get_next_on_page(lock)     ) {         if (lock_rec_get_nth_bit(lock, heap_no)) {             break;         }     }      return(lock); }

鎖維護以頁的粒度,不是一個最高效直接的方式,明顯的時間換空間,這種設計使得鎖的開銷很小。某一事務對任一行上鎖的開銷都是一樣的,鎖數量的上升也不會帶來額外的內存消耗。

每個事務都對應一個trx_t的內存對象,其中保存著該事務鎖信息鏈表和正在等待的鎖信息。因此存在如下兩種途徑對鎖進行查詢:

  • 根據事務: 通過trx_t對象的trx_locks鏈表,再通過lock_t對象中的trx_locks遍歷可得某事務持有、等待的所有鎖信息。
  • 根據記錄: 根據記錄所在的頁,通過space id、page number在lock_sys_t結構中定位到lock_t對象,掃描bitmap找到heap_no對應的bit位。

上述各種數據結構,對其整理關系如下圖所示:

一文聊聊Mysql鎖的內部實現機制

注:

  • lock_sys_t中的slot顏色與lock_t顏色相同則表明lock_sys_t slot持有lock_t
    指針信息,實在是沒法連線,不然圖很混亂

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
国产视频一视频二| 97超碰在线视| 另类小说第一页| 国产福利精品一区二区三区| av不卡在线免费观看| 99久久免费观看| 手机看片福利盒子久久| 亚洲AV无码成人精品一区| 在线观看av的网址| 国产日韩成人内射视频| 亚洲自拍偷拍一区二区三区| 国产综合av在线| 午夜天堂在线视频| 97国产精东麻豆人妻电影| 爽爽爽在线观看| 91精品91久久久中77777老牛| 手机免费av片| av网站在线不卡| 久久这里只有精品23| 欧美中文字幕在线观看视频 | www.xxx亚洲| 黄瓜视频免费观看在线观看www| 国产中文字幕乱人伦在线观看| 超碰成人在线播放| 日本熟妇人妻中出| 欧美,日韩,国产在线| 在线播放 亚洲| 日韩欧美国产片| 亚洲精品午夜在线观看| 欧洲黄色一级视频| 一区二区三区四区久久| 国产美女视频免费看| 国产一区二区在线免费播放| www国产精品内射老熟女| 97超碰人人澡| 波多野结衣家庭教师在线播放| 日本中文字幕一级片| 国产精品亚洲天堂| 特黄特黄一级片| 中文字幕久久av| 粉色视频免费看| 日韩一级理论片| 成人午夜激情av| 国产小视频精品| 亚洲综合日韩欧美| 欧美精品久久久久久久久25p| 男人插女人下面免费视频| 激情五月婷婷久久| 天天综合天天添夜夜添狠狠添| 日本中文字幕二区| 丁香色欲久久久久久综合网| av在线免费观看国产| 日韩少妇内射免费播放| 高清一区在线观看| 成人在线观看www| 久久久久久久香蕉| 波多野结衣综合网| 妺妺窝人体色www在线观看| 伊人网在线综合| www.av毛片| 午夜肉伦伦影院| 国产免费观看高清视频| 日本黄色三级大片| 日韩不卡一二三| 欧美变态另类刺激| 亚洲一级片网站| 亚洲人成无码www久久久| 搡女人真爽免费午夜网站| 久久久国产精华液999999 | 国产中文字幕视频在线观看| 91黄色小网站| 日韩一级特黄毛片| av免费中文字幕| 毛葺葺老太做受视频| 中文字幕 日韩 欧美| www.av毛片| 亚洲成人手机在线观看| 黄色免费视频大全| 喜爱夜蒲2在线| 中文字幕在线综合| 漂亮人妻被中出中文字幕| 国产精品av免费| 青青青在线视频免费观看| 日韩成人三级视频| 国产三级三级三级看三级| 国产又粗又长又爽视频| 午夜精品中文字幕| 91视频免费版污| 青青艹视频在线| av网站手机在线观看| 五月天丁香花婷婷| 国产又大又黄又粗又爽| 成人在线观看a| 国产精品一区二区免费在线观看| 日韩中文字幕亚洲精品欧美| 亚洲成人福利在线| 手机视频在线观看| 成人免费毛片播放| 久久综合久久色| 免费观看精品视频| 一本大道熟女人妻中文字幕在线| 国产欧美123| 黄色网zhan| 免费看啪啪网站| 日韩在线一区视频| 国产又大又黄又猛| 国产亚洲天堂网| 超碰成人免费在线| 男女午夜激情视频| 欧美日韩亚洲第一| 亚洲欧洲日本精品| 夜夜爽久久精品91| 国产欧美123| 日本www在线视频| 怡红院av亚洲一区二区三区h| 国产中文字幕乱人伦在线观看| 国产主播自拍av| 国产精品无码专区av在线播放| 少妇黄色一级片| 污污动漫在线观看| 精产国品一二三区| 免费视频爱爱太爽了| 黄色成人在线免费观看| 亚洲不卡视频在线| 17c丨国产丨精品视频| 欧美一级片中文字幕| 亚洲人视频在线| www国产免费| 国产男女激情视频| 日韩国产精品毛片| 久久精品香蕉视频| 亚洲高清视频免费| 国产高清www| 手机在线看福利| 国产免费黄色一级片| 天天看片天天操| 无码专区aaaaaa免费视频| 99九九99九九九99九他书对| 精品少妇人欧美激情在线观看| 亚洲色成人www永久在线观看| 日本成人性视频| 久久久精品麻豆| www.99热这里只有精品| 爱豆国产剧免费观看大全剧苏畅| 日韩亚洲欧美视频| 国产九九九视频| 黄色片在线免费| 黄色一级片黄色| 裸体大乳女做爰69| www.精品在线| 人妻少妇被粗大爽9797pw| 毛片在线视频观看| 国产精品久久久久久9999| 每日在线更新av| www.av91| 草草草视频在线观看| 亚洲一区二区三区观看| 国产真实乱子伦| 欧美精品一区免费| 中文精品无码中文字幕无码专区 | 超碰97免费观看| 日本www.色| 精品久久久久av| 久久久999免费视频| 一本色道久久88亚洲精品综合| 日本一极黄色片| 91蝌蚪视频在线| 国产美女视频免费看| 亚洲精品手机在线观看| av在线无限看| 亚洲综合日韩欧美| 日韩av在线中文| 久久久久久久高清| 激情文学亚洲色图| 大肉大捧一进一出好爽视频| 天天操狠狠操夜夜操| 欧美精品久久久久久久自慰| 亚洲精品久久久中文字幕| 欧美一区二区激情| 国产精品波多野结衣| 好男人www社区| 日本一道本久久| 欧美另类videosbestsex日本| 国产又大又黄又粗又爽| 国产l精品国产亚洲区久久| 精品一区二区三区无码视频| 欧美精品 - 色网| 日本在线视频www| 91专区在线观看| 97干在线视频| 黄色一级片黄色| 国产精品一二三在线观看| 亚洲精品中文字幕乱码无线| 97公开免费视频| 国产成人久久婷婷精品流白浆| 分分操这里只有精品| 亚洲色欲久久久综合网东京热| 永久免费黄色片| 国产又黄又爽免费视频| 91欧美一区二区三区|