1. 程式人生 > 其它 >java實現雙向連結串列

java實現雙向連結串列

InnoDB儲存引擎

InnoDB 引擎是MySQL資料庫的一個重要的儲存引擎、跟所有的二進位制安裝包裡面、和其它的儲存引擎相比、InnoDB引擎的優點是支援事務、以及引數完整性(有外來鍵)等。MySQL5.5.5以後預設的儲存引擎都是InnoDB引擎。

InnoDB的邏輯架構原理

InnoDB的邏輯架構有三個組成部分,分別是:在記憶體中的架構(In-Memory Structures)、作業系統快取(Operating System Cache)和在硬碟上的架構(On-Disk Structures);這三個架構組成了一款高效能的InnoDB儲存引擎。

記憶體中的架構(In-Memory Structures)

InnoDB在記憶體架構上主要分成四個部分,分別是:緩衝池(Buffer Pool)、寫緩衝(Change Buffer)、日誌緩衝(Log Buffer)以及自適應雜湊索引(Adaptive Hash Index)。

1.緩衝池(Buffer Pool)
緩衝池是一塊用於快取被訪問過的表和索引資料的記憶體區域,緩衝池允許在記憶體中處理一些被使用者頻繁訪問的資料,在某一些專用的伺服器上,甚至有可能使用80%的實體記憶體作為緩衝池。緩衝池的存在主要是為了通過降低磁碟IO的次數來提升資料的訪問效能。

2.寫緩衝(Change Buffer)
寫緩衝是為了快取緩衝池(Buffer Pool)中不存在的二級索引(Secondary Index)頁的變更操作的一種特殊的記憶體資料結構。

​	這些變更通常是一些Insert、Update、Delete等DML操作引發的,如果有一些其它的讀操作將這些被變更的二級索引頁加進了緩衝池(Buffer Pool),則這些變更會被馬上合併至緩衝池中以保證使用者可以讀取到一致的資料。


3.日誌緩衝(Log Buffer)
InnoDB將資料的每次寫優化為了批量寫,這便以降低磁碟IO的次數,為了防止一些資料尚未寫入硬碟就斷電了,需要記錄日誌;而日誌緩衝就是用來快取一些即將要被寫入磁碟日誌檔案(log files)中的資料。


4.自適應雜湊索引(Adaptive Hash Index)
在InnoDB中,使用者是不可以直接去建立雜湊索引的,這個自適應雜湊索引是InnoDB為了加速查詢效能,會根據實際需要來決定是否對於一些頻繁需要被訪問的索引頁構建雜湊索引,它會利用key的字首來構建雜湊索引。這樣做可以提高查詢效能,因為索引採用類似B+樹的結構進行儲存,B+樹的單key查詢時間複雜度為O(log2n),但是優化為雜湊索引後,單key的查詢時間複雜度就為O(1)了。

作業系統快取(Operating System Cache)

作業系統為了提升效能而降低磁碟IO的次數,在InnoDB的快取體系與磁碟檔案之間,加了一層作業系統的快取/頁面快取。使用者態innodb儲存引擎的程序向作業系統發起write系統呼叫時,在核心態完成頁面快取寫入後即返回,如果想立即將頁面快取的內容立即刷入磁碟,innodb儲存引擎需要發起fsync系統呼叫才可以。

硬碟上的架構(On-Disk Structures)

-- InnoDB在硬碟上總共分為六個部分,分別是表(Tables)、表空間(Tablespaces)、索引(Indexes)、雙寫緩衝(Doublewrite Buffer)、Redo日誌和Undo段

1.表(Tables)
-- 如果已經指定了資料的預設儲存引擎,那麼建立表的時候,無需指定再指定儲存引擎。

-- 預設情況下,建立InnoDB表的時候innodb_file_per_table引數是開啟的,它表明使用者建立的表和索引,會被以單表單檔案的形式放入到file-per-table表空間中。

-- 如果禁用了該引數innodb_file_per_table,那麼表及索引會被放入系統表空間(System Tablespaces)中。

-- 如果建立表的時候,想要把表建立在通用表空間(General Tablespaces)中,那麼需要使用者使用CREATE TABLE … TABLESPACE語法來建立表結構。

        

2.表空間(Tablespaces)
-- 系統表空間(System Tablespaces):系統表空間主要用於儲存雙寫緩衝、寫快取以及使用者建立的表和索引(當innodb_file_per_table被禁用的情況下)
 
 -- file-per-table表空間(file-per-tableTablespaces):儲存使用者建立的表和索引資料,預設情況下(innodb_file_per_table引數是啟用的)

-- 通用表空間(General Tablespaces):通用表空間允許使用者儲存一些自己想要放進通常表空間的表或資料,需要使用者建立表的時候,自己指定採用通用表空間,上面講表的時候已經介紹過。

-- 回滾表空間(Undo Tablespaces):回滾表空間是為了儲存回滾日誌,通常回滾日誌在表空間會以回滾段(Undo Segments)的形式存在。

-- 臨時表空間(Temporary Tablespaces):臨時表空間用於儲存使用者建立的臨時表,或者優化器內部自己建立的臨時表。


3.索引(Indexes)
-- 索引存在的目的主要是為了加速資料的讀取速度,InnoDB採用BTree(實際為優化改進後的B+樹索引)。主鍵索引也是聚集索引,二級索引都是非聚集索引。自適應雜湊索引是InnoDB為了加速查詢效能,它自己按需在記憶體中對載入進記憶體的BTree索引優化為雜湊索引的一種手段。


4.雙寫緩衝(Doublewrite Buffer)
-- 雙寫緩衝是一個在系統表空間System Tablespaces中儲存區,在這個儲存區中,在InnoDB將頁面寫入InnoDB資料檔案中的適當位置之前,會先從緩衝池中重新整理頁面 。如果在頁面寫入過程中發生作業系統,儲存子系統或mysqld程序崩潰,則InnoDB可以在崩潰恢復期間從雙寫緩衝中找到頁面的原來的資料。


5.Redo日誌
-- redo即redo日誌,是用於記錄資料庫中資料變化的日誌,只要你修改了資料塊那麼就會記錄redo資訊。你的每次操作都會先記錄到redo日誌中,當出現例項故障(像斷電),導致資料未能更新到資料檔案,則資料庫重啟時須redo,重新把資料更新到資料檔案。


6.Undo段
-- undo即undo段,是指資料庫為了保持讀一致性(原子性),儲存歷史資料在一個位置。 用於記錄更改前的一份copy,用於回滾、撤銷還原。

mysql> show global variables like '%undo%';
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| innodb_max_undo_log_size | 1073741824 |
| innodb_undo_directory    | ./         |
| innodb_undo_log_truncate | OFF        |
| innodb_undo_logs         | 128        |
| innodb_undo_tablespaces  | 0          |
+--------------------------+------------+
5 rows in set (0.00 sec)

mysql> show global variables like '%truncate%';
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_purge_rseg_truncate_frequency | 128   |
| innodb_undo_log_truncate             | OFF   |
+--------------------------------------+-------+
2 rows in set (0.00 sec)

innodb儲存引擎執行流程

-- 執行一條更新sql語句,儲存引擎執行流程可以分為三大階段,8個小步驟:

1.三大階段
-- 執行階段:資料載入到記憶體,寫undo log,更新記憶體中資料,寫redo log buffer

-- 事務提交階段:redo log和binlog刷盤,commit標記寫入redo log中

-- 寫入磁碟:後臺io執行緒隨機把記憶體中髒資料刷到磁碟上
# 注:InnoDB儲存引擎中的每一條修改資料的SQL都是一個事務。



2.八個小步驟
-- 把該行資料從磁碟載入到buffer pool中,並對該行資料進行加鎖

-- 把舊資料寫入undo log,以便修改出錯情況下的回滾

-- 在buffer pool中的資料更新,得到髒資料

-- 把修改後的資料寫入到redo log buffer當中

-- 準備提交事務redo log刷入磁碟

-- 把修改的操作記錄準備寫入binlog日誌

-- 把binlog的檔名和位置寫入commit標記,commit標記寫入redolog中(redo log中存放的修改後的資料與binlog中的修改操作對應上,雙管齊下),事務才算提交成功;否則不會成功

-- IO執行緒Buffer Pool中的髒資料刷入磁碟檔案,完成最終修改
# 注:髒資料就是寫入了記憶體中還沒有來得及寫入硬碟的資料就稱之為髒資料。

InnoDB中程序

innodb儲存引擎是多執行緒的模型,因此其在後臺有多個不同的後臺執行緒,負責處理不同工作任務。

1、master thread

master thread是一個非常核心的後臺執行緒,主要負責將緩衝池中的資料非同步刷到磁碟,保障資料的一致性,其中包括髒頁的重新整理、合併插入緩衝(insert buffer) undo頁的回收。

2、IO thread

-- 在Innodb儲存引擎中大量使用了AIO(Async IO)來處理寫IO請求,這樣可以極大提高了資料庫的效能。而IO thread 的工作主要負責這些IO請求的回撥(call back)處理。

-- innodb 1.0版本之前共有4個IO thread ,分別是write 、read 、insert buffer和log io thread。在linux平臺下,iO thread 的數量不能進行調整,但是在window平臺上可以通過引數innodb_file_io_thread來增大IO thread來增大IO thread ,從innodb 1.0.x版本開始,read thread 和write thread分別增大到了4個,並且不再使用innodb_file_io_threads引數,而是分別使用innodb_read_io_thread和innodb_write_io_threads引數進行設定。

mysql> show variables like '%io_thread%';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_read_io_threads  | 4     |
| innodb_write_io_threads | 4     |
+-------------------------+-------+
2 rows in set (0.00 sec)

3、Purge Thread

-- 事務被提交後,其所使用的undolog可能不再需要,因為需要purge thread來回收已經使用並分配的undo頁。在innodb1.1版本之前,purge操作僅在innodb儲存引擎的master thread中完成,而從innodb1.1版本開始,purge操作可以獨立到單獨的執行緒中進行,以此來減輕master thread的工作,從而提供cpu的使用率以及提升儲存引擎的效能,使用者可以在配置檔案中進行配置: 

mysql> show variables like '%purge_thread%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| innodb_purge_threads | 4     |
+----------------------+-------+
1 row in set (0.01 sec)


-- 檢視IO thread程序狀態
mysql> show engine innodb status\G
*************************** 1. row ***************************
  Type: InnoDB
  Name: 
Status: 
=====================================
2021-09-27 15:20:40 0x7fa18c620700 INNODB MONITOR OUTPUT
=====================================
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
327 OS file reads, 158 OS file writes, 31 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s

-- 可以看到IO thread 0為insert buffer thread。io thread 1為log thread.之後就是根據引數innodb_read_io_thread及innodb_write_io_threads來設定的讀寫執行緒,並且讀執行緒iD總是小於寫執行緒。


4、Page cleaner thread

Page cleaner thread作用是將之前版本中的髒頁的重新整理操作都放入到單獨的執行緒中來完成,而其目的是為了減輕master thread 的工作及對於使用者查詢執行緒的阻塞,進一步提高innodb儲存引擎的效能。

注:當記憶體資料頁跟磁碟資料頁內容不一致的時候,我們稱這個記憶體頁為“髒頁”。