InnoDB學習筆記之一

  • 2019 年 11 月 6 日
  • 筆記

InnoDB學習筆記

簡要介紹

innodb存儲引擎是第一個完整支援ACID事務的MySQL存儲引擎,其特點是行鎖設計、支援MVCC、支援外鍵、提供一致性非鎖定讀。從MySQL5.1版本開始,MySQL資料庫允許存儲引擎開發商以動態的方式載入引擎,這樣存儲引擎的更新可以不受MySQL資料庫版本的限制。從MySQL5.5版本開始,它是默認的表存儲引擎。

體系架構

InnoDB存儲引擎的體系架構如下圖所示:

圖中可以看到,InnoDB存儲引擎有多個記憶體塊,可以認為這些記憶體塊組成了一個大的記憶體池,記憶體池的主要工作有如下幾種:

  • 維護所有進程/執行緒需要訪問的多個記憶體數據結構
  • 快取磁碟上的數據,方便快速的讀取,同時在對磁碟文件的數據修改之前在這裡快取
  • 重做日誌redo log緩衝。

1.後台執行緒

innodb存儲引擎是多執行緒模型,它的後台有多個不同的執行緒,負責不同的任務,這裡簡單介紹一下:

1.1 Master Thread

這是一個核心的後台執行緒,主要負責將緩衝池中的數據一步刷新到磁碟,保證數據的一致性,包括臟頁的刷新、合併插入緩衝、UNDO頁的回收等。

1.2 IO Thread

在InnoDB存儲引擎中使用了大量的Async IO來處理IO請求,這樣可以極大的提高資料庫的性能,而IO執行緒的主要工作是負責這些IO請求的回調處理。

1.3 Purge Thread

事務被提交之後,其所使用的undolog可能不再需要,因此需要PurgeThread來回收已經使用並分配的undo頁,以前Purge Thread是集成在Master Thread中的,從InnoDB1.1版本開始,purge操作可以獨立到單獨的執行緒中執行,從而提高CPU的使用率以及提升存儲引擎的性能。InnoDB1.2版本開始,InnoDB支援多個Purge Thread,其目的是為了進一步加快undo頁的回收。

1.4 Page Cleaner Thread

該執行緒的作用是將之前版本中的臟頁的刷新操作都放入到單獨的執行緒中來完成。而目的是為了減輕原Master Thread的工作以及對於用戶查詢執行緒的阻塞,從而提高Innodb存儲引擎的性能。

2.記憶體

2.1 緩衝池

緩衝池簡單來說就是一塊記憶體區域,通過記憶體的速度來彌補磁碟速度較慢對資料庫性能的影響,在資料庫中進行讀取頁的操作,首先將從磁碟督導的頁放到緩衝池中,下一次再督導相同的頁時,首先判斷該頁是否在緩衝池中,若在,則該頁在緩衝池中被命中,否則讀取磁碟上的頁。

對於InnoDB而言,緩衝池通過innodb_buffer_pool_size來設置,

mysql ::>>show variables like 'innodb_buffer_pool_size';  +-------------------------+-----------+  | Variable_name           | Value     |  +-------------------------+-----------+  | innodb_buffer_pool_size |  |  +-------------------------+-----------+   row in set (0.00 sec)  

緩衝池中快取的數據類型還有:索引頁、數據也、undo頁、插入緩衝、自適應哈希索引、Innodb存儲引擎的所資訊、數據字典資訊等。如下圖所示:

如果我們想增加緩衝池的實例,可以通過innodb_buffer_pool_instances來進行配置,在配置文件中將innodb_buffer_pool_instances設置為大於1的值就可以得到多個緩衝池實例。使用show engine innodb status可以查看每個緩衝池的狀態。

mysql> show engine innodb statusG  *************************** 1. row ***************************    Type: InnoDB    Name:  Status:  =====================================  -11-20 :: 0x7fbbc84b0700 INNODB MONITOR OUTPUT  =====================================  Per second averages calculated from the last  seconds  -----------------  BACKGROUND THREAD  -----------------  srv_master_thread loops:  srv_active,  srv_shutdown,  srv_idle  srv_master_thread log flush and writes:  ----------  SEMAPHORES  ----------  OS WAIT ARRAY INFO: reservation count  OS WAIT ARRAY INFO: signal count  RW-shared spins , rounds , OS waits  RW-excl spins , rounds , OS waits  RW-sx spins , rounds , OS waits  Spin rounds per wait: 626.00 RW-shared, 184.00 RW-excl, 0.00 RW-sx  ------------  TRANSACTIONS  ------------  Trx id counter  Purge done for trx's n:o < 184678 undo n:o < 0 state: running but idle  History list length  LIST OF TRANSACTIONS FOR EACH SESSION:  ---TRANSACTION , not started   lock struct(s), heap size ,  row lock(s)  ---TRANSACTION , not started   lock struct(s), heap size ,  row lock(s)  ---TRANSACTION , not started   lock struct(s), heap size ,  row lock(s)  --------  FILE I/O  --------  I/O thread  state: waiting for completed aio requests (insert buffer thread)  I/O thread  state: waiting for completed aio requests (log thread)  I/O thread  state: waiting for completed aio requests (read thread)  I/O thread  state: waiting for completed aio requests (read thread)  I/O thread  state: waiting for completed aio requests (read thread)  I/O thread  state: waiting for completed aio requests (read thread)  I/O thread  state: waiting for completed aio requests (write thread)  I/O thread  state: waiting for completed aio requests (write thread)  I/O thread  state: waiting for completed aio requests (write thread)  I/O thread  state: waiting for completed aio requests (write thread)  Pending normal aio reads: [, , , ] , aio writes: [, , , ] ,   ibuf aio reads:, log i/o's:, sync i/o's:  Pending flushes (fsync) log: ; buffer pool:   OS file reads,  OS file writes,  OS fsyncs  0.00 reads/s,  avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s  -------------------------------------  INSERT BUFFER AND ADAPTIVE HASH INDEX  -------------------------------------  Ibuf: size , free list len , seg size ,  merges  merged operations:   insert , delete mark , delete  discarded operations:   insert , delete mark , delete  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  Hash table size , node heap has  buffer(s)  0.00 hash searches/s, 0.00 non-hash searches/s  ---  LOG  ---  Log sequence number  Log flushed up to  Pages flushed up to  Last checkpoint at   pending log flushes,  pending chkp writes   log i/o's done, 0.00 log i/o's/second  ----------------------  BUFFER POOL AND MEMORY  ----------------------  Total large memory allocated  Dictionary memory allocated  Buffer pool size  Free buffers  Database pages  Old database pages  Modified db pages  Pending reads  Pending writes: LRU , flush list , single page  Pages made young , not young  0.00 youngs/s, 0.00 non-youngs/s  Pages read , created , written  0.00 reads/s, 0.00 creates/s, 0.00 writes/s  No buffer pool page gets since the last printout  Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s  LRU len: , unzip_LRU len:  I/O sum[]:cur[], unzip sum[]:cur[]  --------------  ROW OPERATIONS  --------------   queries inside InnoDB,  queries in queue   read views open inside InnoDB  Process ID=, Main thread ID=, state: sleeping  Number of rows inserted , updated , deleted , read  0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s  ----------------------------  END OF INNODB MONITOR OUTPUT  ============================     row in set (0.00 sec)  

第82行下面就是buffer pool的詳細內容,這裡需要說明的是,關於緩衝池,還有很多細節的內容,明天將使用一篇文章詳細展開。

2.2 重做日誌緩衝

InnoDB存儲引擎除了有緩衝池外,還有重做日誌緩衝,InnoDB存儲引擎首先將重做日誌資訊放入到這個緩衝區,然後按照一定頻率將其刷新到重做日誌文件中,重做日誌緩衝一般不需要設置的很大,因為一般情況下每一秒鐘會將重做日誌刷新到日誌文件中,因此用戶只需要保證每秒產生的事務在這個緩衝大小之內即可。該值可以由innodb_log_buffer_size來控制,默認為8MB。

重做日誌在下列三種情況下會將重做日誌緩衝中的內容刷新到外部磁碟的重做日誌文件中。

  • Master Thread每一秒將重做日誌緩衝刷新到重做日誌文件
  • 每個事務提交時會將重做日誌緩衝刷新到重做日誌文件
  • 當重做日誌緩衝池剩餘空間小於1/2時,重做日誌緩衝將刷新到重做日誌文件

2.3額外的記憶體池

在InnoDB中,記憶體的管理是通過一種稱為記憶體對的方式進行的,在對一些數據結構本身的記憶體進行分配時,需要從額外的記憶體池中進行申請,當該區域的記憶體不夠時,會從緩衝池中進行申請。例如,分配了緩衝池,但是緩衝池中的幀緩衝還有相應的緩衝控制對象,這些對象記錄了一些諸如LRU、鎖等資訊,而這個對象的記憶體需要從屋外的記憶體池中申請。因此,申請了大的InnoDB緩衝池時,也應該考慮增大額外記憶體池的值。