邏輯儲存結構圖
表空間
表空間檔案在Linux下存放在 /var/lib/mysql檔案中的 xxx.ibd 檔案就是表空間檔案
表空間檔案用來儲存,記錄,索引等資料。
段
段分為,資料段(Leaf node segment) ,索引段(Non-leaf node segment),回滾段(Rollback segment),InnoDB是索引組織表,資料段就是B+樹的葉子節點,索引段就是非葉子節點,段用來管理Extend(區)。
一個段相當於一張表
區
區是表空間的單元結構,每個區大小為1M,預設情況下InnoDB儲存引擎頁大小為16k,一個區一共16個連續的頁。
頁
頁,是InnoDB儲存引擎磁碟管理的最小單元。
每個區預設16KB,為了保證頁的連續性,InnoDB儲存引擎每次從磁碟申請4到5個區。
行
行指的是InnoDB儲存的資料
表結構中倆個隱藏欄位
Trx_id:最後一次操作事務的id
Roll pointer:指標,指向增刪改之前的資料,可以拿這個找到修改之前的資料。
MySQL5.5版本後,預設使用InoDB儲存引擎。
它擅長事務處理,具有崩潰恢復性特性!
下圖為InnoDB架構圖,左邊為記憶體結構,右邊為磁碟結構。
緩衝池是主記憶體的一個區域,裡面可以快取磁碟上經常操作的真實資料。
在執行增刪改查操作的時候,先操作快取池中的資料(如果沒有,從磁碟載入並且快取)
然後以一定頻率重新整理到磁碟,從而減少磁碟IO,加快處理速度
在快取池中有一塊一塊的,這個是頁。
快取池以頁為單位,底層採用連結串列資料結構管理Page。
根據狀態將Page分為三類:
介紹
更改快取區,主要針對非唯一的二級索引。
在執行DML語句時,如果這些資料頁不在Buffer Poor中,不會直接操作磁碟,而是將資料變更在更改快取區Change Buffer中。
在未來資料被讀取的時候,再將資料合併恢復到Buffer Pool中,再將合併後的資料重新整理到磁碟中。
意義
和聚集索引不同,二級索引是非唯一的!
並且二級索引以相對隨機的順序插入。
同樣的刪除和更新可能會影響索引樹中不相鄰的二級索引頁,如果每一次都操作磁碟,會造成大量磁碟IO。
有了ChangeBuffer後,我們可以在緩衝池中進行合併處理減少磁碟IO
紀錄檔快取區,用來儲存要寫入磁碟中的log紀錄檔資料(redo log 、undo log)。
預設大小16MB,紀錄檔快取區的紀錄檔會定期重新整理到磁碟中。如果需要更新、插入、或刪除多行的事務,增加紀錄檔快取區大小可以節約磁碟IO
在系統變數中設定即可
關鍵字:
innodb_log_buffer_size 快取區大小
innodb_flush_log_at_trx_commit 紀錄檔重新整理到磁碟的時機
1代表的是紀錄檔在每次事務提交時寫入並重新整理到磁碟
0代表每秒將紀錄檔寫入並重新整理到磁碟一次
2代表紀錄檔在每次事務提交後寫入,並且每秒重新整理到磁碟一次
自適應雜湊索引,用於優化Buffer Pool資料的查詢。
InnoDB儲存引擎會監控表上各索引頁的查詢,如果觀察到hash索引可以提高速度,就會建立hash索引。
這個叫自適應雜湊索引
可以在系統變數中查詢是否開啟自適應雜湊索引
關鍵字是 adaptive_hash_index
系統表空間是change Buffer的存放區域。
關鍵字:innodb_data_file_path
系統表空間存放路徑
存放每個表的獨立表空間
預設是開啟的-->開啟後代表每一張表都會生成對應的表空間檔案。
xxx.ibd結尾的檔案都是表的表空間檔案
檢視變數 innodb_file_per_table看是開的還是關的
裡面存放了表結構,表資料,索引
通用表空間,需要手動通過
create tablespace 表空間名 add datafile '表空間對應的磁碟檔案.ibd' engine=innodb;
建立通用表空間。
在建立表的時候可以指定該表空間
create table 表名(
欄位....
)engine=儲存引擎 tablespace 表空間名;
復原表空間,MYSQL範例在初始化的時候會自動建立倆個預設的undo表空間(初始大小16M)用來存放undo log紀錄檔
預設叫 undo_001和undo_002
用來儲存使用者建立的臨時表。
雙寫緩衝區,innoDB儲存引擎會將資料頁衝Buffer Pool重新整理到磁碟前,先將資料頁寫入雙寫緩衝區檔案中,便於系統異常時恢復資料。
雙寫緩衝區檔案:xxx.dblwr
用來實現事務的永續性。
該紀錄檔檔案由倆個部分組成:重做紀錄檔緩衝區(redo log buffer)和重做紀錄檔檔案(redo log)
重做紀錄檔緩衝區:是在記憶體中
重做紀錄檔檔案:是在磁碟在
事務提交後會把所有修改的資訊存放在該紀錄檔中,用於重新整理髒頁到磁碟,發生錯誤時,進行資料恢復使用
以迴圈的方式寫入重做檔案,涉及到倆個檔案:ib_logfile0和ib_logfile1
作用:將Innodb緩衝池的資料在合適的時機重新整理到磁碟檔案中。
分為四類:
Master Thread
核心後臺執行緒,負責排程其他執行緒。還負責將緩衝池中的資料非同步重新整理到磁碟中,保持資料的一致性。
還包括,髒頁的重新整理,合併插入緩衝,undo頁的回收
IO Thread
在InoDB儲存引擎中大量使用了AIO來處理IO請求,這樣可以極大提高資料庫效能,IO Thread主要負責以下IO請求的回撥
執行緒型別 | 預設個數 | 責任 |
---|---|---|
Read thread | 4 | 負責讀操作 |
write thread | 4 | 負責寫操作 |
Log thread | 1 | 負責將紀錄檔緩衝區重新整理到磁碟 |
Insert buffer thread | 1 | 負責將寫緩衝區內容重新整理到磁碟 |
關於AIO(非同步IO)和IO(同步IO)
同步就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件事做完了才能做下一件事。
非同步的概念和同步相對。當一個非同步過程呼叫發出後,呼叫者不能立刻得到結果(在此期間,呼叫者可以去幹一些別的事情)。實際處理這個呼叫的部件在完成後,通過狀態、通知和回撥。
Purge Thread
主要用於回收事務已經提交的undo log,在事務提交之後,undo log可能不需要了,就用這個來回收。
Page Cleaner Thread
協助Master Thread重新整理髒頁到磁碟的執行緒,他可以減輕Master Thread的工作壓力,減少阻塞。
在增刪改查的時候,會操作記憶體結構區域,如果裡面沒有資料就從。磁碟結構中載入,然後進行操作。
最後在特定時間會自動從記憶體結構中重新整理到磁碟中。在磁碟中進行持久化儲存下來
事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有操作作為一個整體一起向系統提交復原操作請求。
這些操作要麼同時成功要麼同時失敗。
原子性
事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗。
一致性
事務完成時,必須使所有的資料保持一致性。
隔離性
資料庫系統提高隔離機制,保證事務在不受外部並行操作影響的獨立環境執行。
永續性
事務一旦提交或回滾,他對資料庫的資料改變就是永久的。
事務的原子性,一致性,永續性都是由redo log和undo log實現的
事務的隔離性是由 鎖機制和MVCC實現的。
重做紀錄檔,記錄的是事務提交時資料頁的物理修改,用來實現事務的永續性。
該紀錄檔檔案由倆部分組成:
重做紀錄檔緩衝(redo log buffer)
在記憶體中
重做紀錄檔檔案(redo log file)
在磁碟中
當事務提交後會把所有修改資訊都存放到該紀錄檔檔案中,用於在重新整理髒頁到磁碟中,發生錯誤時,進行資料的恢復。
大概流程:
使用者端A對innoDB儲存引擎的表進行增刪改事務操作
先存取記憶體結構中的緩衝池,如果增刪改資料在其中不存在,
就會從磁碟中讀取資料再重新整理到緩衝池(這個資料必須是唯一索引,否則會先進入到更改緩衝區)
在緩衝池中變成髒頁,並記錄在redolog buffer中,後直接重新整理到磁碟中
如果髒頁在一段時間後重新整理到磁碟中報錯了,可以通過redo log進行恢復。
使用redo log直接重新整理到磁碟結構的好處
事務一般是一組多條的增刪改查操作,故事務提交的時候會隨機的操作多條的記錄。
這些記錄會操作多條資料頁,這樣會產生大量的隨機磁碟IO
而直接將redo log檔案非同步重新整理到磁碟io中,由於它是紀錄檔檔案,紀錄檔檔案都是追加的,此時是順序磁碟IO,這樣會節約大量的磁碟IO
這種機制叫WAL(Write-Ahead Logging)(先寫紀錄檔)
然後過一段時間髒頁紀錄檔才會重新整理到磁碟中。
故倆份紀錄檔是迴圈清理的
事務的redo log紀錄檔是為了解決髒頁重新整理到磁碟出錯時進行資料的恢復使用的,用來保證資料的永續性
undo log紀錄檔是用來保證事務的原子性的。
undo log也叫回滾紀錄檔,用於記錄資料被修改前的資訊,作用為:提供回滾和MVCC
redo log記錄的是物理紀錄檔!
undo log記錄的是邏輯紀錄檔,可以認為當執行delete 一條記錄時,undo log中會記錄一條對應的insert記錄,反之同理。
當執行rollback時,就可以從undo log中的邏輯記錄讀取到對應內容,從而進行回滾。
Undo log銷燬
undo log在事務執行時產生,事務提交時,並不會馬上刪除undo log,因為這些紀錄檔可能還用於MVCC
Undo log儲存
undo log採用,段的方式進行管理和記錄,存放在前面介紹的rollback segment回滾中,內部包含了1024個undo log segment
這個段是邏輯儲存結構的段哦~
我們讀取的是記錄的最新版本,讀取時還要保證其他並行事務不能修改當前記錄,會對讀取的記錄進行加鎖,
對於我們日常的操作,如:select...lock in share mode(共用鎖),select...for update,update,insert,delete(排他鎖)
都是一種當前讀。
案例:
在RR的隔離級別下
簡單的select(不加鎖)就是快照讀,讀取的是記錄資料的可見版本,可能是歷史資料,不加鎖是非阻塞讀。
全稱Multi-Version Concurrency Control 多版本並行控制。
指的是維護一個資料的多個版本,使得讀寫操作沒有衝突。
快照讀為MYSQL實現MVCC提供了一個非阻塞讀功能,MVCC的具體實現,還需要依賴,資料庫的三個隱藏欄位、
undo log紀錄檔、readView
當我們建立了表除了自己本身建立的欄位,innoDB引擎會自動給我們建立三個欄位
分別是:
隱藏欄位 | 含義 |
---|---|
DB_TRX_ID | 最近修改事務ID,記錄插入這條記錄或者最後一次修改該記錄的ID(事務id) |
DB_ROLL_PTR | 回滾指標,指向這條記錄的上一個版本,用於配合undo log指向上一個版本 |
DB_ROW_ID | 隱藏主鍵,如果表結構沒有指定主鍵,就會生成該隱藏欄位 |
可以檢視表空間檔案內容來檢視隱藏欄位資訊
事務id是自增的!
在MYSQL中提供了一個命令來檢視表空間檔案的記錄資訊
ibd2sdi xxx.ibd
回滾紀錄檔,在insert、update、delete的時候產生的便於資料回滾的紀錄檔
當insert的時候,產生的undo log紀錄檔只在回滾時需要,在事務提交後,可被立即刪除。
當update、delete的時候,產生的undo log紀錄檔不只是回滾時需要,在快照讀時也需要,不會被立即刪除。
Undo log版本鏈
不同事務或相同事務對同一條記錄進行修改,會導致該記錄的undo log生成一個記錄的版本連結串列,連結串列的頭部是最新的舊記錄,連結串列的尾部是最早的舊記錄。
執行順序:
從上到下代表執行順序。在同一行代表同一時間執行。
ReadView(讀檢視)是快照讀SQL執行時MVCC提取資料的依據,記錄並維護系統當前活躍的事務(未提交的)id
ReadView中包含了四個核心欄位
欄位 | 含義 |
---|---|
m_ids | 當前活躍的事務id集合 |
min_trx_id | 最小活躍的事務ID |
max_trx_id | 預分配事務ID,當前最大事務ID+1(因為事務ID是自增的) |
creator_trx_id | ReadView建立者的事務ID |
版本鏈資料存取規則
trx_id 代表的是當前事務的id
用這個id和ReadView的四個核心欄位進行比對
trx_id == creator_trx_id 可以存取該版本 這個條件成立代表資料是當前這個事務更改的
trx_id < min_trx_id 可以存取該版本 這個條件成立,說明資料已提交
trx_id > max_trx_id 不可以存取該版本 這個條件成立,說明事務是在ReadView生成之後才開啟的
min_trx_id <= trx_id <= max_trx_id 如果trx_id不在m_ids中,就可以存取該版本
這個條件成立,說明資料已經提交。
根據隔離級別的不同ReadView生成時機不同
在Read Committed隔離級別下
在事務第一次執行快照讀時都生成一個Read view
在Repeatable read隔離級別下
在事務第一次執行快照讀時生成,後續複用這個Read view
在事務第一次執行快照讀時都生成一個Read view
第一個快照讀,讀取情況
這個快照讀,根據規則,讀取的是0x00002這個地址的資料,對應著事務2修改後的資料內容。
第二個快照讀,讀取情況
這個快照讀,根據規則讀取到的是,0x00003地址的資料內容,就是事務3修改後的資料。
在RR隔離級別下,只有事務在第一次執行快照讀的時候生成ReadView,後續複用這個ReadView
具體的和RC規則一致,不重複講解。
隱藏欄位+Undo log版本鏈+ReadView組成MVCC
MVCC+鎖構成事務的隔離機制
事務的一致性由Redo log和undo log共同保證