日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一文了解OOM及解决方案,你还看不明白?

發布時間:2023/11/30 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文了解OOM及解决方案,你还看不明白? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

InnoDB總體結構

首先我們來看官網的一張圖(圖片來源于MySQL官網):

從上圖中可以看出其主要分為兩部分結構,一部分為內存中的結構(上圖左邊),一部分為磁盤中的結構(上圖右邊)

內存結構

InnoDB內存中的結構主要分為:Buffer Pool,Change Buffer和Log Buffer三部分。

Buffer Pool

Buffer Pool是InnoDB緩存表和索引的一塊主內存區域,Buffer Pool允許直接從內存中處理經常使用的數據,從而加快處理速度,帶來一定的性能提升。 但是緩存總有放滿的時候,當緩存滿了新來的數據怎么處理呢?Bufer Pool中采用的是LRU(least recently used,最近最少使用)算法,LRU列表中最前面存的是高頻使用頁,尾部放的是最少使用的頁。當有新數據過來而緩存滿了就會覆蓋尾部數據。

假如我們有一條查詢語句非常大,返回的結果集直接就超過了Buffer Pool的大小,而這種語句使用場景又是極少的,可能查詢這一次之后很久不會查詢,而這一次就將緩存占滿了,將一些熱點數據全部覆蓋了。為了避免這種情況發生,InnoDB對傳統的LRU算法又做了改進,將LRU列表分拆分為2個,如下圖(圖片來源于MySQL官網):

該算法在new子列表中保留大量頁面(5/8),old子列表包含較少使用的頁面(3/8);old子列表中數據可能會被覆蓋,該算法具體操作如下:

  • 3/8的Buffer Pool空間用于old子列表

  • 列表的中點是new子列表的尾部與old子列表的頭部之間的邊界

  • 當InnoDB將一個頁面讀入緩沖池時,它首先將它插入到中間點(old子列表的頭)。讀取的頁面是由用戶發起的操作(比如SQL查詢)或InnoDB自動執行的預讀操作

  • 訪問old子列表中的頁面使其“young”,并將其移動到new子列表的頭部。如果讀取的頁是由用戶發起的操作,那么就會立即進行第一次訪問,并使頁面處于young狀態;如果讀取的頁是由預讀發起的操作,那么第一次訪問不會立即發生,而且可能直到覆蓋都不會發生。

  • 操作數據時,Buffer Pool中未被訪問的頁會逐漸移到尾部,最終會被覆蓋。

默認情況下,查詢讀取的頁面會立即移動到新的子列表中,這意味著它們在緩沖池中停留的時間更長。

Change Buffer

Change Buffer是一種特殊的緩存結構,用來緩存不在Buffer Pool中的輔助索引頁, 支持insert, update,delete(DML)操作的緩存(注意,這個在MySQL5.5之前叫做Insert Buffer,僅支持insert操作的緩存)。當這些數據頁被其他查詢加載到Buffer Pool后,則會將數據進行merge到索引數據葉中。

InnoDB在進行DML操作非聚集非唯一索引時,會先判斷要操作的數據頁是不是在Buffer Pool中,如果不在就會先放到Change Buffer進行操作,然后再以一定的頻率將數據和輔助索引數據頁進行merge。這時候通常都能將多個操作合并到一次操作,減少了IO操作,尤其是輔助索引的操作大部分都是IO操作,可以大大提高DML性能。

如果Change Buffer中存儲了大量的數據,那么可能merge操作會需要消耗大量時間。

為什么Change Buffer只能針對非聚集非唯一索引

因為如果是主鍵索引或者唯一索引,需要判斷數據是否唯一,這時候就需要去索引頁中加載數據判斷而不能僅僅只操作緩存。

Change Buffer什么時候會merge

總體來說,Change Buffer的merge操作發生在以下三種情況:

  • 輔助索引頁被讀取到Buffer Pool時。 當執行一條select語句時,會去檢查當前數據頁是否在Change Buffer中,如果在,就會把數據merge到索引頁

  • 該輔助索引頁沒有可用空間時。 InnoDB內部會檢測輔助索引頁是否還有可用空間(至少有1/32頁),如果檢測到當前操作之后,當前索引頁剩余空間不足1/32時,會進行一次強制merge操作

  • 后臺線程Master Thread定時merge。 Master Thread是一個非常核心的后臺線程,主要負責將緩沖池中的數據異步刷新到磁盤,保證數據的一致性。

Adaptive Hash Index

Adaptive Hash Index,自適應哈希索引。InnoDB引擎會監控對索引頁的查詢,如果發現建立哈希索引可以帶來性能上的提升,就會建立哈希索引,這種稱之為自適應哈希索引,InnoDB引擎不支持手動創建哈希索引。

Log Buffer

日志緩沖區是存儲要寫入磁盤日志文件的一塊數據內存區域,大小由變量innodb_log_buffer_size 控制,默認大小為16MB(5.6版本是8MB):

SHOW VARIABLES LIKE 'innodb_log_buffer_size';-- global級別,無session級別

上文講述update語句更新流程一文中,我們只提到了Buffer Pool用來代替緩存區,通過本文對內存結構的分析,實際上Buffer Pool中嚴格來說還有Change Buffer,Log Buffer和Adaptive Hash Index三個部分,DML操作會緩存在Change Buffer區域,而寫redo log之前會先寫入Log Buffer,所以Log Buffer又可以稱之為redo Log Buffer。

Log Buffer什么時候寫入redo log

一個大的Log Buffer空間大允許運行大型事務,而無需在事務提交之前將redo log數據寫入磁盤。Log Buffer中的數據會定期刷新到磁盤,那么Log Buffer的數據又是如何寫入磁盤的呢?Log Buffer數據flush到磁盤有三種方式,通過變量innodb_flush_log_at_trx_commit 控制,默認為1。 |value|描述|

  • 當設置為0時,由于數據還在內存,所以崩潰后數據基本會被丟失

  • 當設置為2時,由于數據已經實時寫到redo log了,如果磁盤文件沒有被損壞,還是可以恢復的

另外,Mast Thread默認1s進行一次刷盤操作,這個可以通過變量innodb_flush_log_at_timeout控制,默認1s。

SHOW VARIABLES LIKE 'innodb_flush_log_at_timeout';-- global級別,無session級別

磁盤結構

InnoDB引擎的磁盤結構,從大的方面來說可以分為Tablespace和redo log兩部分

Tablespace

Tablespace可以分為4大類,分別是:System Tablespace,File-Per-Table Tablespaces,General Tablespaces,Undo Tablespaces

System Tablespace

系統表空間中包括了 InnoDB data dictionary,doublewrite buffer, change buffer, undo logs 4個部分,默認情況下InnoDB存儲引擎有一個共享表空間ibdata1,如果我們創建表沒有指定表空間,則表和索引數據也會存儲在這個文件當中,可以通過一個變量控制(后面會介紹)。

ibdata1文件默認大小為12MB,可以通過變量innodb_data_file_path來控制,改變其大小的最好方式就是設置為自動擴展。

innodb_data_file_path=ibdata1:12M:autoextend

上面表示默認表空間ibdata1大小為12MB,支持自動擴展大小。

當我們的文件達到一定的大小之后,比如達到了998MB,我們就可以另外開啟一個表空間文件:

innodb_data_home_dir= innodb_data_file_path=/ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend

關于上面的設置有3點需要注意:

  • innodb_data_home_dir如果不設置的話,那么就默認所有的表空間文件都在datadir目錄下,而我們上面指定了2個不同路徑,所以需要把innodb_data_home_dir設為空

  • autoextend這個屬性,只能放在最后一個文件

  • 指定新的表空間文件名的時候,不能和現有表空間文件名一致,否則啟動MySQL時會報錯

當然,表空間可以增大,自然也可以減少,但是一般我們都不會去設置減少,而且減少表空間也相對麻煩,在這里就不展開敘述了。

InnoDB Data Dictionary

InnoDB數據字典由內部系統表組成,其中包含用于跟蹤對象(如表、索引和表列)的元數據。元數據在物理上位于InnoDB系統表空間中。由于歷史原因,數據字典元數據在某種程度上與存儲在InnoDB表元數據文件(.frm文件)中的信息重疊。

Doublewrite Buffer

Doublewrite Buffer,雙寫緩沖區,這個是InnoDB為了實現double write而設置的一塊緩沖區,double write和上面的change buffer一個確保了可靠性,一個確保了性能的提升,是InnoDB中非常重要的兩大特性。

我們先來看下面一張圖:

InnoDB默認頁的大小是16KB,而操作系統是4KB,如果存儲引擎正在寫入頁的數據到磁盤時發生了宕機,可能出現頁只寫了一部分的情況,比如只寫了 4K,這種情況叫做部分寫失效(partial page write),可能會導致數據丟失。

可能有人會說,可以通過redo log來恢復,但是注意,redo log恢復數據有一個前提,那就是頁沒有損壞,如果頁本身已經被損壞了,那么是沒辦法恢復的,所以為了確保萬無一失,我們需要先保存一個頁的副本,如果出現了上面的極端情況,可以用頁的副本結合redo log來恢復數據,這就是double write技術。

double write也是由兩部分組成,一部分是內存中的double write buffer,大小為2MB,另一部分是物理磁盤上的共享表空間中的連續128個頁,大小也是2MB,寫入流程如下圖(圖片來源于《MySQL技術內幕 InnoDB存儲引擎》):

double write機制會使得數據寫入兩次磁盤,但是其并不需要兩倍的I/O開銷或兩倍的I/O操作。通過對操作系統的單個fsync()調用,數據以一個大的順序塊的形式寫入到雙寫入緩沖區。

在大多數情況下默認啟用了doublewrite緩沖區。要禁用doublewrite緩沖區,可通過將變量innodb_doublewrite設置為0即可。

面試資料整理匯總

這些面試題是我朋友進阿里前狂刷七遍以上的面試資料,由于面試文檔很多,內容更多,沒有辦法一一為大家展示出來,所以只好為大家節選出來了一部分供大家參考,需要全部文檔的,關注小編后,點擊這里即可免費領取。

面試的本質不是考試,而是告訴面試官你會做什么,所以,這些面試資料中提到的技術也是要學會的,不然稍微改動一下你就涼涼了

多,沒有辦法一一為大家展示出來,所以只好為大家節選出來了一部分供大家參考,需要全部文檔的,關注小編后,點擊這里即可免費領取。

面試的本質不是考試,而是告訴面試官你會做什么,所以,這些面試資料中提到的技術也是要學會的,不然稍微改動一下你就涼涼了

在這里祝大家能夠拿到心儀的offer!

總結

以上是生活随笔為你收集整理的一文了解OOM及解决方案,你还看不明白?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。