程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL內核InnoDB存儲引擎(卷1)筆記

MySQL內核InnoDB存儲引擎(卷1)筆記

編輯:MySQL綜合教程

MySQL內核InnoDB存儲引擎(卷1)筆記


MySQL內核InnoDB存儲引擎(卷1)

目錄

  • 1 概覽
  • 2 基本數據結構和算法
  • 3 同步機制
  • 4 重做日志
  • 5 mini-transaction(mtr)
  • 6 存儲管理
  • 7 記錄
  • 8 索引頁
  • 9 鎖
  • 10 B+樹索引
  • 11 Insert Buffer
  • 12 緩沖池
  • 13 事務處理
  • 14 數據字典
  • 15 服務管理

    概覽

    基本數據結構和算法

    同步機制

    rw-lock/latch s-/x-:x-可遞歸,s-不可?;以spin獲得,一段時間後進入wait array(信號量?) p38 若sync_primary_wait_array中1000個cell都已分配,則ut_error觸發crash 當持有latch的線程釋放latch後,調用sync_array_signal_object喚醒等待線程

    重做日志

    p42 redo log原來保證事務的持久性(D),undo log用於回滾和MVCCinnodb_flush_log_at_trx_commit=0/1/2redo log VS. bin log 前者記錄的是頁的物理邏輯操作日志設計思想:物理日志記錄頁內的修改(old-new value),邏輯日志記錄對表的操作(insert/delete) LSN(表示事務寫入redo log的字節量?) 對‘檢查點’,表示刷新到磁盤的位置?——不管怎麼說,LSN有一種‘隨時間單調變化’的性質 檢查點:將緩沖池中的頁刷新到磁盤 sharpfuzzy* redo日志的大小是固定的(3GB)->歸檔日志ib_logfile<N>redo日志塊(512B-12-8) 和磁盤扇區大小一樣,保證原子性,不需要double write? 重做日志組*組提交:fsync -> log_flush_up_to 會對最後一個日志塊進行復制恢復:recovery_from_checkpoint_start 表空間第一個頁頭部的FIL_PAGE_FILE_FLUSH_LSN記錄了數據庫關閉時最後刷新頁的LSNrecv_parse_or_apply_log_rec_bodyrecv_add_to_hash_tablerecv_recover_pagerecv_read_in_area 判斷頁所在相鄰的32個頁?

    mini-transaction(mtr)

    FIX rules:修改頁之前需要持有該頁的latchWAL 每個頁需要有一個LSN?LSN溢出怎麼辦? Force-Log-at-Commitmtr_t mtr; mtr_start(&mtr); ... mtr_commit(&mtr); 提交時若mtr->modified==TRUE,先修改緩沖池中的頁*1,然後釋放log_sys->mutex(這是一個熱點) *1 log_reserve_and_write_fast/log_write_slow 快速/慢速2個路徑 更新多行記錄時,MLOG_MULTI_REC_END

    存儲管理

    頁:(space_id, offset) 16KB1 extent = 64 連續的page space header 段(segment) 每張用戶表至少2個段:聚集索引(B+樹)的葉子節點和非葉子節點段一個段最多可以管理32個獨立的頁,和若干區 表空間數據結構:fil_system/space/node_struct4個異步I/O線程:異步讀、異步寫、插入緩存、重做日志

    記錄

    物理記錄 p102 用戶記錄的heap no總是從2開始 偽記錄:Infimum/Supremum(感覺將像是雙鏈表的first/last) p103 VARCHAR類型的NULL不占用磁盤空間,而CHAR NULL用0x00填充大記錄:BLOB/TEXT(溢出頁,extern屬性) 邏輯記錄 dtuple_struct,對大記錄是big_rec_structB+樹索引只定位頁,頁內記錄需要二分掃描 mtype/prtype 行記錄版本(MVCC只是列?):通過隱藏的事務ID列 read_view_struct: low/up_limit_idtrx_ids, n_trx_idscreator p114 函數read_view_sees_trx_id用來判斷當前事務是否可以讀記錄的當前版本,不是,則row_sel_build_prev_vers_for_mysql

    索引頁

    Page Header 頁內記錄根據主鍵是邏輯順序,不是物理順序 Page Directory(定位記錄在頁內的位置) slot?offset的主鍵逆序記錄 Page Cursor*

    p136 理論上,隔離級別越低,事務請求的鎖越少或保持鎖的時間越短幻讀:謂詞鎖 --> key-range locking --> next/previous-key lockingp138 意向鎖:意味著事務希望在更細粒度上加鎖 InnoDB是行級鎖,不會阻止全表掃描以外的請求 lock_rec_struct = { space, page_no, n_bits } 所有鎖對象通過kernel_mutex進行保護(又一個熱點!) 優化:細粒度拆分? p144 LOCK_GAP(代表范圍鎖不包含端點)顯式鎖和隱式鎖**(略)行鎖的維護*(重點,略) 插入更新PURGE一致性的鎖定讀頁的分裂頁的合並 自增鎖(atomic?)死鎖*

    B+樹索引

    聚集 / 輔助分裂操作:btr_page_split_and_insert合並:btr_compress查找:btr_cur_search_to_nth_level p203 對唯一約束的鍵值,需要使用模式PAGE_CUR_GE,而不是LElatch_modecursor DML操作 樂觀插入:btr_cur_optimistic_insert非主鍵更新(主要是列的大小會不會發生變化) btr_cur_optimistic_update --> btr_cur_pessimistic_update(例略) 主鍵更新 刪除 持久游標 btr_pcur_struct自適應哈希索引*

    Insert Buffer

    將多次插入合並為一次操作(提高了非唯一約束輔助索引的插入性能)p237 實現最為困難的在於對死鎖的處理 頁邏輯層次劃分:非IB頁、IB非bitmap頁、bitmap頁p241 異步I/O線程可能引起死鎖問題 --> rw_lock_x_lock_move_ownership

    緩沖池

    LRU、Free和Flush鏈表預讀 p258 隨機預讀 要滿足32個頁中9個已經訪問過且都是活躍的才可能觸發 線性預讀*邏輯預讀 頁的刷新 部分寫問題(?) --> double write(存在於內存的表空間,大小為2MB,這意味著最多128頁/次刷新)

    事務處理

    分類:扁平、帶保存點的扁平、鏈、嵌套、分布式事務系統段*doublewrite段*undo日志存儲 一致性的非鎖定讀 p282 讀取快照不需要加鎖 undo日志實現:回滾段 + undo段 trx_undo_struct undo記錄purge*rollback 7B roll_ptr隱藏列 {rseg_id(1), page_no(4), offset(2)}3個回滾類型:TRX_SIG_{TOTAL_ROLLBACK, ROLLBACK_TO_SAVEPT, ERROR_OCCURRED} commit

    數據字典

    服務管理

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved