數據庫和實例
數據庫(database):物理操作系統文件或其他形式文件類型的集合
實例(instance):mysql數據庫由后台線程以及一個共享內存區組成。
通常情況下,兩者是一對一關系;但是,在集群情況下可能存在一個數據庫被多個數據實例使用的情況。
mysql實例在系統上的表現就是一個進程;
InnoDB存儲架構


innodb 在內存中的緩存池 buffer pool ;
innodb相關的磁盤文件


innodb系統表空間文件:
ibdata1存放:
- 回滾段
- 所有innodb表元數據信息(這就是為什么innodb無法像myisam表一樣,直接將表定義文件 表名.frm 和表數據文件 表名.ibd 拷貝到 另一個庫中,因為還有部分元數據信息在ibdata1文件中)
- double write,insert buffer dump 等等
自動擴展機制
基本參數
查看innodb的配置參數
mysql> show global variables like "%innodb%" ;
基本參數:
innodb_data_home_dir: 系統表空間文件ibdata1存放在哪個目錄下
innodb_log_group_home_dir: 日志文件ib_logfile0/1存放在哪個目錄
innodb_data_file_path: 定義系統表空間文件ibdata1的屬性;
innodb_autoextend_increment: 系統表空間文件每次擴展的大小
innodb_log_file_size: ib_logfile文件大小(寫操作多時可以增大)
innodb_log_files_in_group: 有幾個ib_logfile文件(寫操作多時可以增大 )

innodb_file_per_table:
關鍵;開啟后,會產生表定義文件 表名.frm,和表數據文件 表名.idb,
這樣每個表的數據都會存在自己的.idb文件中;如果 關閉,那么所有的
數據都會 存在系統表空間文件 ibdata1文件中,這會ibdata1 非常繁忙
並且臃腫 龐大,而且ibdata1無法 收縮的,比如線上將一個 大的表 drop掉,
此時ibdata1是無法自動縮小的(需要使用 optimiza table 來優化);而如果開啟,數據存在 .idb文件中,則可以隨時縮小;

innodb數據文件存儲結構

特點:
- 根據主鍵尋址速度很快
- 主鍵值遞增的insert插入效率較好
- 主鍵值隨機insert插入操作效率差
- 因此,innodb表必須指定主鍵,建議使用自增數字;
如果不使用主鍵,系統會自動加上一個6字符字符串的主鍵;
innodb數據塊緩存池
- 數據的讀寫需要經過緩存(緩存在buffer pool 即在內存中)
- 數據以整頁(16K)位單位讀取到緩存中
- 緩存中的數據以LRU策略換出(最少使用策略)
- IO效率高,性能好


innodb_buffer_pool_size:


為了IO效率,數據庫修改的文件都在內存緩存中完成的;那么我們知道一旦斷電,內存中的數據將消失,而數據庫是如何保證數據的完整性的呢?那就是數據持久化與事務日志;
innodb 數據持久化與事務日志
- 事務日志實時持久化
- 內存變化數據(臟數據)增量異步刷出到磁盤
- 實例故障靠重放日志恢復
- 性能好,可靠,恢復快;


如果宕機了則:應用已經持久化好了的日志文件,讀取日志文件中沒有被持久化到數據文件里面的記錄;將這些記錄重新持久化到我們的數據文件中.


優缺點:如果實時的刷新到 磁盤中,要找到x隨機存放的位置,IO消耗大;而如果將修改刷新到日志文件中,因為它是順序讀寫的,速度會快很多。
innodb日志持久化相關參數
innodb_flush_log_at_trx_commit


innodb 行級鎖
- 寫不阻塞讀
- 不同行間的寫相互不阻塞
- 並發性能好
innodb與事務ACID
事務ACID特性完整支持
- 回滾段失敗回滾 A
- 支持主外鍵約束 C
- 事務版本+回滾段=MVCC I
- 事務日志持久化 D
默認可重復讀隔離級別,可以調整
innodb關鍵特性
- 插入緩沖(insert buffer)
- 兩次寫(Double write)
- 自適應哈希索引(adaptive hash index)
- 異步io(Async IO)
- 刷新領接頁(Flush Neighbor Page)
帶來了更好的性能以及更高的可靠性。
1.插入緩沖
使用場景,即非唯一輔助索引的插入操作,因為不是順序的,所以將這些插入操作,
存到插入緩沖中去,然后一段時間統一插入到真的索引中去,此時很有可能有幾條 插入合並操作,
因為他們是對同一索引頁進行的操作,這樣就大大提高了效率。
關鍵就是將一些 離散的操作,緩存起來,然后找到一些對同一個索引頁 進行 操作的 操作項 進行合並,這樣提高了 效率。
2.兩次寫
提高了 數據頁的可靠性。
在應用(apply)重做日志前,用戶需要一個頁的副本,當寫入失效發生時,先通過頁的副本來還原該頁,再進行重做,這就是duble write 。

dublewrite組成
- 內存中的dublewrite buffer,大小2M,
- 物理磁盤上共享表空間中連續的128個頁,即2個區(extend),大小同樣為2M。
對緩沖池的臟頁進行刷新時,不是直接寫磁盤,而是會通過memcpy()函數將臟頁先復制到內存中的doublewrite buffer,
之后通過doublewrite 再分兩次,每次1M順序地寫入共享表空間的物理磁盤上,在這個過程中,因為doublewrite頁是連續的,
因此這個過程是順序寫的,開銷並不是很大。在完成doublewrite頁的寫入后,再將doublewrite buffer 中的頁寫入各個 表空間文件中,
此時的寫入則是離散的。如果操作系統在將頁寫入磁盤的過程中發生了崩潰,在恢復過程中,innodb可以從共享表空間中的doublewrite
中找到該頁的一個副本,將其復制到表空間文件,再應用重做日志。
3.自適應哈希索引
哈希(hash)是一種非常快的查找方法,在一般情況下這種查找的時間復雜度為O(1),即一般僅需要一次查找就能定位數據。
而B+樹的查找次數,取決於B+樹的高度,在生成環境中,B+樹的高度一般3-4層,故需要3-4次的查詢。
innodb會監控對表上個索引頁的查詢。如果觀察到建立哈希索引可以帶來速度提升,則建立哈希索引,稱之為自適應哈希索引(Adaptive Hash Index,AHI)。
AHI有一個要求,就是對這個頁的連續訪問
模式必須是一樣的。
例如對於(a,b)訪問模式情況:
where a = xxx
where a = xxx and b = xxx
訪問模式一樣指的是查詢的條件一樣,若交替進行上述兩種查詢,那么innodb不會對該頁構造AHI,此外AHI還有如下的要求:
- 以該模式訪問了100次
- 頁通過該模式訪問了N次,其中N=頁中記錄*1/16;
AHI啟動后,讀寫速度提高了2倍,輔助索引的連接操作性能可以提高5倍。
AHI,是數據庫自動優化的,DBA只需要指導開發人員去盡量使用符合AHI條件的查詢,
以提高效率。
4.異步IO
sync IO :同步IO 即每進行一次IO操作,此次操作結束才能繼續接下來的操作。
但是如果用戶發需要等待出一條索引掃描的查詢,那么這條SQL查詢語句可能需要掃描多個索引頁,
也就是需要進行多次的IO操作。在每掃描一個頁並等待期完成再進行下一次的掃描是沒有必要的。
異步IO:
用戶可以在發出一個IO請求后立即再發出另一個IO請求,當全部IO請求發送完畢后,等待所有IO操作的完成,這就是AIO。
AIO另一個優勢可以將多個IO,合並為1個IO,以提高IO效率。例如:
用戶需要訪問3頁內容,但這3頁時連續的。同步IO需要進行3次IO,而AIO只需要一次 就可以了。
使用AIO的恢復速度 提高了75%
5.刷新領接頁
工作原理:
當刷新一個臟頁時,innodb會檢測該頁所在區(extent)的所有頁,如果是臟頁,那么一起進行刷新。
這樣做,通過AIO將多個IO寫入操作合並為一個IO操作。在傳統機械磁盤下有着顯著優勢。
innodb_flush_neighbors 參數來控制是否開啟。
總結
- 數據庫與實例
- innodb相關磁盤文件:
-
- ibdata1:
-
- 回滾段
- 表元數據
- double write
- insert buffer dump等
- ib_logfile0/1
- .frm:表定義文件
- .ibd:數據文件,innodb_file_per_table=1
- 性能相關參數:
-
- innodb_log_file_size
- innodb_log_files_in_group
- 原因:當redo log 采用輪尋范式ib_logfile0寫完,寫ib_logfile1完,清楚ib_logfile0並繼續寫入ib_logfile0;當ib_logfile1寫完,ib_logfile0中還有數據沒有持久化到磁盤,又來了新的寫入,此時會阻塞新寫入,強制刷新ib_logfile0到磁盤,再將新寫,寫入ib_logfile0;這樣就是說,logfile越大其寫入越不容易阻塞,寫入性能也就越好。
- 數據節點每頁16K
- innodb數據塊緩存池
-
- 數據讀寫經過緩存池
- 數據以整頁為單位讀取
- LRU策略(最少使用)換出,
- innodb數據持久化:通過事務日志
- innodb_flush_log_at_trx_commit
-
- 0:每秒寫入並持久化一次(不安全,性能高,無論mysql或服務器宕機,都會丟數據)
- 1:每次commit都持久化(安全,性能低,IO負擔重)
- 2:每次commit都寫入內存的redo log緩存,每秒再刷新到磁盤(安全,性能折中,mysql宕機數據不會丟失,服務器宕機數據會丟失)
- innodb關鍵特性
-
- 插入緩沖(insert buffer)
- 兩次寫(Double write)
- 自適應哈希索引(adaptive hash index)
- 異步io(Async IO)
- 刷新領接頁(Flush Neighbor Page)