mysql數據庫(InnoDB引擎)筆記

基於《MySQL技術內幕(InnoDB存儲引擎)第2版》一書整理的筆記

注:使用Sublime Text編輯的,博客顯示效果並不理想,可粘貼到本地使用Sublime Text打開閱讀。

 

存儲引擎是基於表的,而不是基於數據庫的。

MyISAM引擎不支持事務,不支持行級鎖,支持全文索引,主要面向一些OLAP數據庫應用。MyISAM的緩衝池只緩存索引文件,不緩存數據文件。

InnoDB後臺線程:
    Master Thread:
        日誌緩衝刷新到磁盤,刷新髒頁到磁盤,合併插入緩衝,UNDO頁的回收。
    IO Thread:
        InnoDB大量使用AIO來處理I/O請求。InnoDB1.0之前版本有4個IO Thread,分別是read,write,insert buffer,log IO Thread。InnoDB1.0.x版本開始,read thread和write thread分別增大到了4個。
    Purge Thread:
        事務被提交後,其所使用的undolog可能不再需要,因此需要Purge Thread來回收已經使用並分配了的undo頁。
    Page Cleaner Thread:
        InnoDB1.2x版本後引入的,將髒頁刷新放到單獨的線程中執行,減輕Master Thread的工作,降低用戶查詢的延遲。

InnoDB中內存:
緩衝池:
    InnoDB的存儲引擎是基於磁盤的,由於CPU的磁盤的速度差異很大,使用內存緩衝池來彌補磁盤速度較慢對數據庫的影響。在數據庫進行讀操作時,首先將磁盤讀到的頁放入緩衝池中,下次讀到相同的頁時,判斷該頁是否在緩衝池中,若在,則直接讀取緩衝池中數據,否則從磁盤讀取。
    頁的修改操作通過CheckPoint機制刷新回磁盤。
    緩衝池的數據頁類型有:索引頁,數據頁,undo頁,插入緩衝,自適應哈希索引,InnoDB存儲的鎖信息,數據字典信息等。

    InnoDB緩衝池基於優化的LRU算法進行管理。在LRU列表中加入midpoint,新讀取到頁不是放在LRU列表的首部,而是放在midpoint位置,這是因爲某些sql操作,如索引或數據的掃描操作,會訪問表中的許多頁,這些頁通常來說只在這次查詢中需要,而不是熱點數據,如果放在LRU首部很可能導致熱點數據被從LRU列表刪除。還需要引入一個參數來表明數據頁到達mid位置後需要多久才能被放到LRU熱端。

重做日誌緩衝:
    重做日誌緩衝刷新到磁盤的情況:
        Master Thread每秒鐘將重做日誌緩衝刷新到重做日誌文件。
        每個事務提交時會將重做日誌緩衝刷新到重做日誌文件。
        當重做日誌緩衝池剩餘空間小於1/2時,重做日誌緩衝刷新到重做日誌文件。
額外的內存池

爲了避免數據丟失,當前事務數據庫系統普遍採用了 Write Ahead Log策略,先寫重做日誌,再提交事務。

CheckPoint主要解決以下幾個問題:
    1縮短數據庫的恢復時間
    2緩衝池不夠用時,將髒頁刷回磁盤
    3重做日誌不可用時,刷新髒頁
        重做日誌不可用的情況:因爲當前事務數據庫系統對重做日誌的設計都是循環使用的,並不能無限增大。重做日誌可以被重用的部分指這些日誌已經不再需要,這部分數據就可以被覆蓋使用,如果此時重做日誌還需要使用的話,就強制CheckPoint,將緩衝池中的頁至少刷新到當前重做日誌的位置。

兩種CheckPoint:Sharp CheckPoint 、 Fuzzy CheckPoint
    Sharp CheckPoint:發生數據庫關閉時,將所有髒頁刷新回磁盤
    Fuzzy CheckPoint:只刷新一部分髒頁,而不是所有。
        4種可能導致Fuzzy CheckPoint的情況:
            1Master Thread CheckPoint
            2FLUSH_LRU_LIST CheckPoint
            3Aysnc/Sync Flush CheckPoint
            4Dirty Page to much CheckPoint

Master Thread 
    Master Thread具有最高的線程優先級別。內部由多個循環組成:主循環(loop),後臺循環(background loop),刷新循環(flush loop),暫停循環(suspend loop)
    主循環(loop):主要進行兩大部分的操作:每秒鐘的操作和每10秒種的操作
        每秒鐘的操作包括:
            1日誌緩衝刷新到磁盤,即使該事務還未提交(總是)  (解釋了爲什麼再大的事務的提交時間也是很短的)
            2合併插入緩衝(可能 ,當前一秒內IO次數小於5次則執行)
            3刷新至多100個innodb緩衝池的髒頁到磁盤(可能,判斷緩衝池中髒頁比例是否超過設置的閾值)
            4如果當前沒有用戶活動,則切換到background loop(可能)
        每10秒的操作包括:
            1刷新100個髒頁到磁盤(可能,過去10秒鐘內IO次數小於200則執行)
            2合併至多5個插入緩衝(總是)
            3將日誌緩衝刷新到磁盤(總是)
            4刪除無用的Undo操作(總是)
            5刷新100個或10個髒頁到磁盤(總是)
    後臺循環(background loop):如果當前沒有用戶活動或關閉數據庫,則會切換到background loop
        執行的操作:
            1刪除無用的Undo頁(總是)
            2合併20個插入緩衝(總是)
            3跳回到主循環(總是)
            4不斷刷新100個頁直到符合條件(可能,跳轉到flush loop中完成)
    若flush loop中無事可做,InnoDB引擎會切換到suspend_loop,將Master Thread掛起。

InnoDB引擎的關鍵特性
    1插入緩衝(Insert Buffer)
        含義:對於非聚集索引的插入或更新操作, 並不是每次直接插入到索引頁(由於非聚集索引的插入的離散型),而是判斷插入的非聚集索引頁是否在緩衝區,若是則直接插入,若不在則先放入InsertBuffer,再以一定頻率將Insert Buffer和輔助索引葉子階段進行merge操作,因爲此時通常能夠將多個插入合併到一個操作中,提高插入性能。
        要滿足的兩個條件:
            1索引是輔助索引
            2索引不是唯一的
        合併InsertBuffer時機:
            1輔助索引頁被讀取到緩衝池
            2Insert Buffer Bitmap檢測到該輔助索引頁已無可用空間
            3Master Thread
    2兩次寫(Double Write)
        含義:引入目的爲提高數據庫的可靠性,在應用重做日誌前,用戶需要一個頁的副本,當寫入失效發生時,先通過該頁的副本還原該頁,再按重做日誌進行恢復,主要避免某個頁寫入一半發生了錯誤而導致頁損壞。
        組成:分爲兩部分。一部分是內存中的doublewrite buffer,大小2MB,一部分是物理磁盤上的共享表空間中連續的128頁,即兩個區,也是2MB。
        過程:對緩衝區的髒頁進行刷新時,並不直接寫磁盤,而是先通過memcpy函數將髒頁複製到doublewrite buffer,然後doublewrite buffer分兩次寫,每次1M寫入到共享表空間的物理磁盤,然後馬上調用fsync函數,同步磁盤,避免緩衝寫帶來的問題。
    3自適應哈希索引(Adaptive Hash Index)
        含義:InnoDB會監控對錶上各索引頁的查詢,如果構建哈希索引能夠帶來速度的提升,則會構建哈希索引(AHI)。AHI是根據緩衝池中的B+數索引頁來構建的,不必對整張表構建AHI,因此構建速度很快。InnoDB會根據訪問的模式和頻率自動爲某些熱點數據構建哈希索引。
        要求:
            1這個頁的連續訪問模式必須相同,如where a=XXX或where a=xxx and b=xxx 但是兩種模式不能交替執行。
            2以該模式訪問了100次
            3頁通過該模式訪問了N次,其中N=頁中記錄數/16;
        適用範圍:只適合等值查詢,不適合範圍查詢等
    4異步IO(Async IO)
        優勢:
            1用戶發起IO請求後可以立即執行其他操作無需等待。
            2可以進行IO merge操作,將多個IO請求合併爲一個。
    5刷新鄰接頁(Flush Neighbor Page)
        含義:當刷新髒頁時,InnoDB存儲引擎會檢測該頁所在區的所有頁,如果是髒頁,則一起刷新。
        好處:便於AIO進行IO請求合併(適合於機械硬盤)


第四章:表
索引組織表:InnoDB存儲引擎中,表都是根據主鍵順序組織存放的,這種組織方式爲索引組織表。
    InnoDB中每張表都有主鍵,如果用戶沒有給定主鍵,會採用下列方案創建主鍵:
    1首先判斷表中是否由非空的唯一索引(Unique NOT NULL),如果有將該字段設爲主鍵。(如有多個,則選擇建表時定義索引的第一個)
    2如果不符合上述條件,則會自動創建一個6字節大小的指針。

InnoDB邏輯存儲結構:所有數據被邏輯的存放在一個空間裏,稱爲表空間(tablespace),表空間又由段(segment)區(extent)頁(page)組成。頁中還有一些文檔有時稱爲塊(block)
    表空間:ibdata1,邏輯存儲結構的最高層,所有數據都放在表空間。
    段:表空間由各個段組成,包括數據段(Leaf segement),索引段(Not-leaf segement),回滾段(Rollback segement)等
    區:由連續的頁組成的空間,每個區大小固定爲1MB,默認情況下頁的大小爲16kB,所以默認一個區有64個連續的頁。
    頁:磁盤管理的最小單位,默認爲16KB,頁大小一旦確定就無法修改。常見頁類型有:
        數據頁(B-tree Node)
        Undo頁(Undo log page)
        系統頁(System Page)
        事務數據頁(Transaction system page)
        插入緩衝位圖頁(Insert Buffer Bitmap)
        插入緩衝空閒列表頁(Insert Buffer Free List)
        未壓縮的二進制大對象頁(Uncompressed BOLB Page)
        壓縮的二進制大對象頁(Compressed BOLB Page)
    行:InnoDB引擎是面向列的,也就是數據是按行存儲的。每個也做多存儲16KB/2-200行的記錄(即7992行)。
        行記錄格式分爲:Compact和Redundant(爲兼容之前版本)兩種(屬於Antelope文件格式)
            Compact格式:爲了高效的存儲數據(即在一個頁中放更多的數據)而引入,存儲格式:變長字段長度列表(按列逆序),NULL標誌位,記錄頭信息,列1數據,列2數據。。。每行數據有兩個隱藏列,事務ID列和回滾指針列,另外如果表沒有指定主鍵,則還有一個6字節的列rowid。Compact格式下NULL值不佔任何空間。
            Redundant格式:存儲格式:變長字段偏移列表(按列逆序),記錄頭信息,列1數據,列2數據。。。
        行數據溢出:InnoDB會將某些大的數據真正的數據以外(BLOB,LOB,VARCHAR等並不一定)評判標準:一個頁至少有兩條行記錄。
        新的文件格式Barracuda:Compressed和Dynamic兩種行記錄格式。
            新的兩種行記錄格式對於存放在BLOB中的數據採用了完全的行溢出方式。另外Compressed行記錄格式會對存儲其中的記錄採用zlib的算法進行行壓縮。

約束和索引的區別:約束是一個邏輯概念,用來保證數據的完整性。索引是一個數據結構,既有邏輯概念,又在數據庫中代表物理存儲的方式。

物化視圖:Oracle支持物化視圖,可以預先計算並保存多表的鏈接(Join)或聚集(Group By)等耗時的sql操作,這樣在進行復雜的查詢時可以避免這些耗時的操作。

Mysql支持水平分區,不支持垂直分區。此外Mysql的分區時局部分區索引,一個分區既包含了數據又包含了索引,全局分區是指,數據存放在各個分區,而數據的索引集中存放在一起,目前Mysql不支持全局分區。
    常見的分區方式有:RANGE分區、LIST分區、Hash分區、KEY分區,Columns分區。

第五章、索引與算法
InnoDB支持以下幾種常見的索引:    
    1B+樹索引
        B+樹索引只能找到被查找數據行的頁,再將該頁讀入內存,在頁中查找行。並不能直接找到對應行。
        由於每頁PageDirectory中的糟是按照主鍵存放的,對於頁中的具體記錄是採用二分法查找的。
    2全文索引
    3哈希索引


聚簇索引(clustered index)和輔助索引(secondary index)的區別:聚簇索引葉子節點存放的是一整行的記錄,而輔助索引存放的是指向記錄的指針。因此聚簇索引能夠直接獲取行的信息,輔助索引則還需要一次指針定位。這也意味着更新操作對聚簇索引的影響更大。
聚簇索引的特點:
    聚簇索引對於主鍵的範圍查詢和排序查詢非常快,適合like 'xxx%'(索引前綴查找)。
    聚簇索引的存儲並不是物理上連續的,而是邏輯上連續的。主要體現在以下兩點:
        1數據頁是通過雙向鏈表連接的,頁按主鍵順序連續。
        2頁中記錄也是通過雙向鏈表維護的,物理上可以不按主鍵存儲。
輔助索引:不包含行信息。除了包含鍵值外,每個節點還包含一個書籤(bookmark),用來告訴InnoDB引擎哪裏可以找到與索引相對應的行數據(即相應數據行的聚簇索引鍵,再通過聚簇索引找到對應的行記錄)

Mysql5.5前創建或刪除索引的方式:
    1創建一張新臨時表,表結構爲通過命令ALTER TABLE新定義的結構
    2將原來表數據導入到新臨時表
    3刪除原來表
    4把臨時表命名爲原表
InnoDB 1.0x開始支持一種Fast Index Creation(FIC)的索引創建方式。在創建輔助索引時,對該表加一個S鎖。在創建過程中不需要重建表。刪除輔助索引則只需要Innodb更新內部視圖,並將輔助索引的空間標記爲可用,然後刪除mysql數據庫內部視圖對該表的索引定義即可。

添加B+樹索引的情況:
    1.經常訪問表中很少一部分行記錄時
    2.某個字段取值範圍很廣,幾乎沒有重複時
        show index查詢中的Cardinality值就是索引中不重複記錄數量的預估值
    3.滿足上述條件並且經常作爲查詢條件的字段

Cardinality值:
    對Cardinality值的獲取是通過採樣方式完成(減少開銷)
    對Cardinality值的更新是發生在INSERT和UPDATE操作中,更新策略:
        1表中1/16數據已經發生了變化
        2stat_modified_counter>2000000000(發生變化的次數)
    對Cardinality值的更新是通過對8個葉子節點進行採樣,每次統計也會更新Cardinality值

聯合索引:本質上也是B+樹,不同的是聯合索引的鍵值數量不是1,而是大於等於2(有可能避免排序,如查詢一個人最近購買的N件商品)

覆蓋索引(covering index):即可以從輔助索引中直接得到查詢的記錄,而不需要再訪問一次聚集索引,但輔助索引不包含整行記錄的所有信息,可以減少大量的IO操作。

優化器不選擇使用索引的情況:

Multi-Range Read(MRR)優化:mysql5.6開始支持MRR優化。目的是減少磁盤的隨機訪問,轉化爲較爲順序的數據訪問。可以用來優化,range,ref,eq_ref類型的查詢。
    MRR優化的好處:
        1是數據訪問變得比較順序,查詢輔助索引時,首先根據查詢到的結果根據主鍵進行排序,然後按照主鍵排序的順序進行書籤查找。
        2減少緩衝池中頁被替換的次數。
        3批量處理對鍵值的查詢操作。
    對於InnoDB和MyISAM存儲引擎的範圍查詢和JOIN操作,MRR的工作方式如下:
        1將查詢到的輔助索引鍵值放到一個緩存中,此時緩衝中數據是根據輔助索引鍵值排序的。
        2將緩存中的鍵值根據rowid進行排序。
        3根據rowid的順序來訪問實際數據文件。

Index Condition Pushdown(ICP)優化:mysql5.6開始支持ICP優化。
    在不支持ICP前,進行索引查詢時,先根據索引查找記錄再根據WHERE條件來過濾記錄。引入ICP後可以在取出索引記錄的同時進行WHERE條件過濾(將WHERE的部分過濾操作放在存儲引擎層),大大減少上層sql對記錄的索取(fetch)。
    ICP支持range,ref,eq_ref,ref_or_null類型的操作。

InnoDB中的哈希算法:衝突機制採用鏈表法,哈希函數採用除法散列方式

第六章、鎖
lock和latch:
    latch是一種輕量級鎖,其要求鎖定的時間必須非常短。又可以分爲mutex(互斥鎖)和rwlock(讀寫鎖),其目的是用來保證併發進程操作臨界資源的正確性,通常沒有死鎖檢測的機制。
    lock的對象是事務,用來鎖定數據庫中的對象,如表、頁、行。一般lock的對象僅在事務commit或rollback後釋放,lock有死鎖機制。

鎖(lock)的類型:
    InnoDB提供了兩種標準的行級鎖:
        共享鎖(S Lock):允許事務讀一行數據
        排他鎖(X Lock):允許事務刪除或更改一行數據
    InnoDB支持意向鎖,意向鎖是將鎖的對象分爲多個層次,如果把上鎖的對象看成一個棵樹,那麼對最下層的對象上鎖,也就是對最細粒度的對象上鎖,那麼首先要對粗粒度的對象上鎖。例如,如果要對頁上的記錄r加X鎖,那麼分別需要對數據庫、表、頁上加意向鎖IX鎖,再在記錄r上加X鎖。
    InnoDB的意向鎖爲表級別的鎖,其目的是爲了在一個事務中揭示下一行被請求鎖的類型,其支持兩種意向鎖:
        意向共享鎖(IS Lock):事務想要獲取一張表某幾行的共享鎖
        意向排他鎖(IX Lock):事務想要獲取一張表某幾行的排他鎖
    InnoDB存儲引擎支持的鎖 行級別的鎖,因此意向鎖其實不會阻塞除全表掃描以外的其他操作。

一致性非鎖定讀(REPEATABLE READ級別):InnoDB通過行多版本控制的方式來讀取當前執行時間數據庫中的行數據。如果當前讀取的行正在執行DELETE或UPDATE操作,這時候讀取操作不會因此去等待行上鎖的釋放,而是會讀取一個行的快照數據(數據未修改時的版本)。其實現是通過undo段來完成。
    具體實現:多版本併發控制(MVCC) 參考:  https://www.cnblogs.com/lmj612/p/10598971.html

一致性鎖定讀:InnoDB對SELECT語句支持兩種一致性鎖定讀操作:
    SELECT ... FOR UPDATE (加X鎖)
    SELECT ... LOCK IN SHARE MODE (加S鎖)
    

自增長與鎖:
    解釋:InnoDB的內存中每個含有自增長值的表都含有一個自增長計數器(auto-increment counter),每次插入,這個計數器值就+1,這種實現方式叫做AUTO-INC Locking,是一種特殊的表鎖機制,此鎖並不是事務完成後釋放,而是自增長值插入的SQL語句結束時釋放。
    性能問題:
        1對自增長值的列併發插入性能較差,事務必須等待前一個插入的完成。
        2對於INSERT...SELECT的大數據量的插入會影響插入的性能,因爲另一個事務的插入會被阻塞。
    Mysql版本5.1.22後,InnoDB提供了一種輕量級互斥量的自增長實現機制。

外鍵和鎖:
    解釋:InnoDB中如果對於一個外鍵列沒有顯示添加索引,系統會自動給此列添加一個索引,這樣看可以避免表鎖(爲啥?)
    注意:對於外鍵值的插入或更新,首席按要查詢父表中的記錄,即SELECT父表。但是對父表的SELECT操作並不是使用一致性非鎖定讀的方式,因爲這樣會導致數據不一致,而是採用SELECT ... LOCK IN SHARE MODE的方式,即主動對父表加一個S鎖。如果此時父表已經加了X鎖,則子表的操作會被阻塞。


鎖的算法:
    行鎖的算法:InnoDB引擎上有三種行鎖算法:
        Record Lock:單個行記錄上的鎖
        Gap Lock:間隙鎖,鎖定一個範圍,但不包含記錄本身
        Next-Key Lock:Gap Lock + Recent Lock,鎖定一個範圍,並鎖定記錄本身。
    InnoDB所有的行鎖算法都是基於索引實現的,鎖定的也都是索引或索引區間;
    InnoDB對行的查詢都採用Next-Key Lock,如果一個索引有10,11,13,20這四個值,那麼該索引可能被Next-Key Lock的區間爲(-無窮,10](10,11],(11,13],(13,20],(20,+無窮),其設計的目的是爲了解決Phantom Problem。如果查詢的索引含有唯一屬性,則將其降級爲Recent Lock(查詢的列有唯一索引纔會降級,若是輔助索引則不會,輔助索引除了對加Next-Key Lock外還會對輔助索引的下一個鍵值加上Gap Lock)
    兩種方式顯式關閉Gap Lock:
        1將事務隔離級別設置爲READ COMMITTED
        2將參數innodb_locks_unsafe_for_binlog設置爲1
        可能導致的問題:破壞事務的隔離性,對於replication,可能導致主從數據不一致。

解決Plantom Problem(幻象問題)
    Plantom Problem含義:指同一事務下連續執行兩次相同的SQL操作可能導致不同的結果,第二次SQL語句可能返回之前不存在的行。

髒讀:一個事務可以讀到另一個事務未提交的信息,違反了事務的隔離性。例如:事務A對插入了一條數據,還未提交,事務B讀取時讀到了插入的數據,之後事務A進行了回滾,這樣B就讀到了不存在的數據。

不可重複讀:一個事務多次讀取一個數據集合,由於其間其他事務對數據進行了修改,導致兩次讀取的結果不同。違反了事務的一致性要求。
    髒讀和不可重複讀的區別:髒讀讀到的是未提交的數據,不可重複讀讀到的是已提交的數據。

丟失更新:兩個事務同時對一個數據進行更新操作,導致其中一個事務的更新操作被覆蓋。(即使是最低級別的READ UNCOMMITED也能避免這種情況)

死鎖的處理:
    超時
    wait-for graph(等待圖):是一種更主動的死鎖檢測方式。InnoDB採用這種方式。圖中主要存在兩種信息:
        鎖的信息鏈表
        事務等待鏈表

鎖升級:將當前鎖的粒度降低。例如將1000個行鎖升級爲一個頁鎖,或者將頁鎖升級爲表鎖。
    InnoDB不存在鎖的升級,因爲其不是根據誒個記錄來生成行鎖的,其根據每個事務訪問的每個頁對鎖進行的管理,採用的是位圖的方式,鎖住多少記錄開銷影響不大。

第七章、事務
事物的ACID特性:
    A 原子性(atomicity):事務被看作數據庫的邏輯工作單元。事務中的操作要麼全都成功,要麼全都失敗。
    C 一致性(consistency):事務將數據庫從一種一致性狀態變爲另一種一致性狀態
    I 隔離性(isolation):一個事務的執行不能被其他事務干擾。(任何事物的更新操作直到其提交成功,對其他事務都是不可見的)
    D 永久性(durability):一個事務它對數據庫應該是永久的,即使出現故障其對數據庫的更新也是永久的。

事務的分類:
    扁平事務
    帶保存點的扁平事務
    鏈事務
    嵌套事務
    分佈式事務

事務的實現
    事務的隔離性由鎖機制保證,原子性,一致性,永久性由數據庫的redo log和undo log來完成。redo log保證原子性和永久性,undo log來保證一致性。
    redo和undo可以視爲一種數據庫恢復操作,redo恢復提交事務的頁修改操作,而undo回滾行記錄到某個特定的版本,兩者的記錄內容不同,redo通常是物理日誌,記錄的是頁的物理修改操作,undo是邏輯日誌,根據每行記錄進行記錄。

    redo:分爲兩部分:重做日誌緩衝,重做日誌文件。
        InnoDB通過Force Log at Commit機制保證事務的持久性。即事務提交前,必須先將該事務的日誌寫入重做日誌文件中進行持久化。
        log block:InnoDB存儲引擎中,重做日誌都是以512字節存儲的,這意味着重做日誌緩衝和重做日誌文件都是以塊(block)爲單位的。稱之爲重做日誌塊(redo log block),由於重做日誌塊大小和磁盤扇區大小一樣都是512字節,因此其寫入可以保證原子性,無需doublewrite。

        重做日誌和二進制日誌比較:
            共同點:兩者都記錄了對數據庫操作的日誌。
            區別:
                重做日誌在InnoDB存儲引擎層產生,二進制日誌是mysql上層產生,任何存儲引擎產生的數據庫操作都會記錄在二進制日誌中。
                二進制日誌是一種邏輯日誌,記錄的是對應的sql語句,重做日誌是物理日誌,記錄的是對應頁的修改。
                二進制日誌只在事務提交時寫入日誌,重組日誌在事務進行時不斷提交。

    undo:主要用於回滾操作和MVCC。與redo存放在重做日誌文件中不同,undo存放在表空間的undo segment。    
        undo是邏輯日誌,只是將事務的修改邏輯地取消了,但數據結構和頁本身可能大不相同。例如用戶執行Insert 10W條記錄的語句時,可能系統會爲其申請一個大的段,表空間會增大。但是執行rollback操作時,申請的存儲空間並不會回收。實際上對於Insert操作,數據庫回滾是是執行相應的delete操作,對於update操作,會執行一個相反的update操作。
        undo log會產生redo log,因爲undo log也需要持久性的保護。

purge操作:
    舉例:
        delete和update操作可能並不會立即執行,例如sql語句:delete from t where a=1。表t上有列a的聚集索引,有列b的輔助索引,上述delete操縱僅僅是將主鍵列的delete flag=1,記錄並沒有刪除還是存在於B+樹中,其次對於輔助索引上的a=1,b=1的記錄同樣沒有操作,甚至沒有產生undo log。其真正的刪除操作被延遲到purge操作中完成。
    這樣的設計是因爲:innoDB支持MVCC,所以事務不能在記錄提交時立即處理。

附:
mysql爲什麼使用B+樹而不使用B樹
B樹每個節點都代表一個記錄,都存有數據域,這使得B樹的每個非葉子節點比B+要大的多,這也使得每次索引的I/O次數增加。
另外相比於B樹,B+樹有將所有葉子節點串聯起來的指針,可以順序訪問,很方便全表遍歷等操作,另外對於區間訪問也很方便。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章