1. 程式人生 > >MySQL自身對性能的影響

MySQL自身對性能的影響

9.png 哈希 dap purge locate 事務性 loop 也不會 reat

MySQL體系結構

想要了解MySQL自身對性能的影響,就需要先熟悉MySQL的體系結構和常用的存儲引擎。MySQL並不完美,卻足夠靈活,能夠適應高要求的環境,例如Web類應用。同時,MySQL既可以嵌入到應用程序中,也可以支持數據倉庫、內容索引和部署軟件、高可用的冗余系統、在線事務處理系統(OLTP)等各種應用類型。

MySQL最重要、最與眾不同的特性是它的存儲引擎架構,這種架構的設計將查詢處理(Query Processing)及其他系統任務(Server Task)和數據的存儲/提取相分離。這種處理和存儲分離的設計可以在使用時根據性能、特性,以及其他需求來選擇數據存儲的方式。

MySQL的體系結構,第一層:

客戶端層,這一層代表了各種可以通過MySQL連接協議連接到MySQL服務器的客戶端,例如 PHP、JAVA、C API、ODBC、JDBC等 。可以看得出來這些並不是MySQL所獨有的,大多數基於網絡的C/S (客戶端/服務器) 的工具或者服務都有類似的架構。這一層主要是:連接處理,授權認證和安全相關的一些功能。每個連接到MySQL客戶端都會在服務器進程中擁有一個線程,這個連接的查詢,只會在這個單獨的線程中執行,也就是說的每個連接的查詢只能用到一個CPU的核心

第二層:

第二層架構是MySQL比較有意思的部分。大多數MySQL的核心服務功能都在這一層,這一層包括了:查詢緩存器、查詢解析器、查詢優化器等。以及MySQL所有的內置函數(例如,日期、時間、數學和加密函數等)。總之,所有跨存儲引擎的功能都是在這一層來實現的。因為這一層稱之為MySQL服務層,這一層中實現了與存儲引擎無關的特性。那什麽是與存儲引擎無關的特性呢?比如說select語句,這個語句對所有的存儲引擎來說,所要實現的功能都是一樣的。(獲取存儲在文件中的數據,並根據我們的過濾條件進行過濾,然後把數據顯示出來)所以這個select語句的功能是可以在MySQL服務層實現的,但具體如何從文件中獲得我們所要查詢的數據,則是由下一層存儲引擎層來實現的。

第三層:

存儲引擎層,這是區別其他數據庫最大的地方,MySQL定義了一系列存儲引擎的接口,所以我們也可以根據這些接口開發、定制出符合自己需求的存儲引擎,例如Innodb一開始就是第三方公司所開發的存儲引擎。存儲引擎主要負責MySQL中數據的存儲和提取,每個存儲引擎都有它的優勢和劣勢。存儲引擎API包含了幾十個底層函數,但存儲引擎不會去解析SQL(註:InnoDB是一個例外,它會解析外鍵定義,因為MySQL服務層本身沒有實現該功能),不同存儲引擎之間也不會相互通信,而只是簡單地響應上層服務器的請求。目前常用的存儲引擎有:innodb、myisam、XtraDB、CSV、Memory等。由於MySQL這種插件式的存儲引擎所帶來的靈活性,使得我們可以很方便的根據不同的特點選擇不同的存儲引擎。註意,存儲引擎是針對於表的而不是針對於庫的,(理論上一個庫裏面不同的表可以使用不同的存儲引擎,但不建議這麽幹)

MySQL體系結構圖如下:
技術分享圖片


MySQL常用存儲引擎之MyISAM

MyISAM是在mysql5.58之前的版本默認的存儲引擎,MyISAM存儲引擎將表存儲在兩個系統文件中,一個是數據文件以.MYD結尾,另一個是索引文件以.MYI結尾的。對於mysql所有的存儲引擎都會有一個以.frm結尾的文件,這個文件是記錄表的結構的文件,所以.MYD和.MYI文件是MyISAM存儲引擎特有的。

MyISAM的特性:

特性一:

首先是並發性及鎖級別,MyISAM使用的是表級鎖而不是行級鎖,這就意味著,對表中的數據修改時,要對整個表進行加鎖。而對表中的數據進行讀取的時候也需要對所有的表加共享鎖,從這裏可以看出使用MyISAM引擎的表讀取和寫入這兩種操作是互斥的。MyISAM對讀寫混合的操作的並發性不是很好,如果是只讀的操作,並發性還算可以接受,因為共享鎖並不會阻塞共享鎖。

特性二:

第二個特性需要從表損壞修復上來看,MyISAM支持由於意外關閉而損壞MyISAM表進行檢查和修復操作,但這裏指的並不是事務的恢復。因為myisam並不是支持事務的存儲引擎,所以它也不可能有事務恢復的相關日誌。需要註意的是對MyISAM表進行修復會有可能造成數據的丟失,使用 check table tablename 命令可以對表進行檢查,使用 repair table tablename 命令則可以對有問題的表進行修復。

這裏使用一個簡單的例子演示一下這個特性,在數據庫中新建一個myIsam表,存儲引擎為myIsam,建表的SQL語句如下:

create table myIsam(id int,c1 varchar(10))engine=myisam;

建表完成後,在相應的MySQL數據存儲目錄中會出現myIsam.frm和myIsam.MYD以及myIsam.MYI這三個文件,其中myIsam.frm存放的是表的結構信息,myIsam.MYD文件存儲的是myIsam表的數據信息,myIsam.MYI則存放的是索引的信息:
技術分享圖片

這時候我們使用check table myIsam;檢查這個表,然後使用repair table myIsam;修復表,Msg_text 顯示ok代表沒有問題:
技術分享圖片

如果發現有損壞的表,可以使用repair table myIsam;來進行修復。除此之外,mysql還提供了一個命令行的工具:myisamchk 。這個工具也可以對myisam表進行修復,但是需要註意的是:如果使用這個命令行工具來修復myisam表的話,要先把mysql服務先停掉。因為如果在mysql運行的時候使用這個工具對表進行修復,有可能對表進行一些損壞。

特性三:

MyISAM支持的索引,myisam支持全文索引,而且是在mysql5.7之前版本中,唯一原生就是支持全文索引的官方存儲引擎。另外myisam表還支持對 test、belog等字段建立前500個字符的這種前綴索引。

特性四:

MyISAM是支持表壓縮的,如果myisam是一張很大的只讀表的時候,也就是說在表創建完並導入數據後,就不會在對表進行任何操作了,那麽我們就可以對這樣的表進行壓縮操作,可以減少磁盤I/O。如果對一張表壓縮,可以使用myisampack命令來對表進行壓縮表中數據。對表中的數據是獨立進行壓縮的,在讀取單數據的時候呢,不必對整個表來進行解壓。

使用如下命令,即可對一張表進行壓縮:

myisampack -b myIsam.MYI

需要註意的是,對壓縮後的表只能進行讀操作,不能進行寫操作,如果此時向myIsam表插入數據就會報錯:
技術分享圖片

MyISAM存儲引擎的限制:

在 mysql5.0 版本之前默認單表的最大存儲大小是4G,如果想要存儲超過4G的數據的時候,需要在建表的是指定MAX_RowsAVG_ROW_LENGTH參數的值,這兩個參數的值相乘的大小就是表存儲的最大的大小。如果對已存在的大表修改這兩個參數,等於對表進行重建,會花費一些時間。在Mysql5.0之後單表最大支持256TB

MyISAM適用的場景:

  • 非事務型應用,myisam 本身是非事務存儲引擎,是不支持事務的
  • myisam支持壓縮,所以適合只讀類的應用
  • 在mysql5.7之前myisam是唯一個支持空間函數的一個存儲引擎,所以也適合空間類應用

MySQL常用存儲引擎之Innodb

在mysql5.58之後的版本默認存儲引擎是Innodb,代替了之前的myisam。與myisam不同的是,Innodb是事務存儲引擎,Innodb是支持事務特性的,適合大部分的應用場景,也更適合處理大量的小事務。

Innodb與myisam另一個區別是存儲方式的不同,Innodb有自己的表空間的概念,表空間數據是存儲在表空間之中的,具體存放到哪個表空間由 innodb_file_per_table 這個參數來決定。如果這個參數為ON,則會為每個Innodb表建立一個獨立的表空間,以tablename.ibd為擴展名的文件。如果這個參數為OFF則會把數據存放到系統共享表空間,也就是ibdataX 這個空間裏,X代表一個從 1 開始的整數。

我們可以使用如下SQL語句來查看該參數的值:

show variables like ‘innodb_file_per_table‘;

執行結果如下:
技術分享圖片

接下來新建一個myinnodb表,看看這個表是如何存儲的,建表的SQL語句如下:

create table myinnodb(id int, c1 varchar(10)) engine=‘innodb‘;

可以看到有兩個文件一個是myinnodb.frm、myinnodb.ibd,其中.frm文件是記錄表結構的,而.idb文件就是表數據實際存儲的地方了:
技術分享圖片

註:MySQL8.x 版本有所改變,只會存在.ibd文件,不會有.frm文件,具體可以查閱官方文檔

我們可以使用如下命令更改表的存儲方式,例如改為存儲在系統表空間中:

set global innodb_file_per_table=off;

接下來新建一個myinnodb_g表,建表的SQL語句如下:

create table myinnodb_g(id int, c1 varchar(10)) engine=‘innodb‘;

此時可以看到只有一個myinnodb_g.frm文件,沒有.idb文件了:
技術分享圖片

關於系統表空間和獨立表空間如何選擇:

1.對表空間的管理方式比較:mysql5.6之前的Innodb的innodb_file_per_table參數的默認值為off,所以所有的數據都會存儲在系統表空間中。在一個繁忙的系統中,會發現系統表空間會不斷的增長,一旦我們的磁盤空間出現不足,需要釋放一些磁盤空間時,就不得不刪除大量的無效數據及一些無關緊要的日誌數據,但刪除完之後會發現系統表空間並不會縮小。而收縮系統表空間的唯一方法就是把整個數據庫中的所有Innodb表導出後,刪除Innodb相關的表空間文件,接著重啟MySQL進行表空間的重建,然後再將之前導出的數據再次導入進去。想也知道這個過程是麻煩又耗時的,我們不可能在生產環境中這麽幹。由於系統表空間無法簡單的收縮文件大小,會造成大量空間的浪費,並且產生大量的磁盤碎片,從而降低系統的性能。如果使用獨立表空間的話這個問題就很好解決了,我們對表數據進行清理之後,可以直接通過optimize table命令來收縮系統文件,並且不需要重啟MySQL,也不會影響數據庫的訪問。從這一點來看,使用獨立表空間顯然要比系統表空間要好得多。

2.然後我們再來看看使用系統表空間對I/O會有什麽影響:對於系統表空間來說,因為只有一個文件,所以多個表空間進行數據刷新的時候,實際上在文件系統上是順序進行的,這樣就會產生大量的I/O瓶頸。而獨立的表空間來說,每個表都有自己獨立的表空間文件。所以在數據寫入的時候,可以同時向多個文件刷新數據。結論:對於頻繁寫入的操作,不適合使用系統表空間存儲數據,最好用獨立表空間進行存儲。建議,在Innodb下使用獨立表空間進行數據存儲。

由於版本原因,可能有些數據存儲在系統表空間中,這裏簡單說明把原來存在於系統表空間中的表轉移到獨立表空間中的方法及步驟:

  1. 使用mysqldump導出所有數據庫表數據
  2. 停止MySQL服務,修改innodb_file_per_table參數的值為on,並刪除Innodb相關的表空間文件
  3. 重啟MySQL服務,重建Innodb系統表空間
  4. 重新導入數據

Innodb存儲引擎的特性:

特性一:

Innodb是一種事務性存儲引擎,完全支持事務的ACID特性,也就是原子性、一致性、隔離性以及持久性。Innodb存儲引擎為了實現原子性、一致性以及持久性這三個特性,它使用了兩個特殊的日誌類型:Redo Log(重做日誌) 和 Undo Log(回滾日誌)。

Redo Log主要實現事務的持久性,Redo Log主要由兩部分組成,一是存在於內存中的重做日誌緩沖區,該緩沖區大小由innodb_log_buffer_size參數來決定。二是重做日誌文件,即ib_logfile開頭的文件。

Undo Log主要作用是用於幫助未提交事務進行回滾和實現MVCC多版本並發控制,所以Redo Log中存儲的是已提交的事務,Undo Log存儲的則是未提交的事務。因此我們對Innodb表中的數據進行修改時,不僅會產生Redo Log,還會產生一定數量的Undo Log。Redo Log基本上是順序寫入的,因為在數據庫運行時不需要對Redo Log進行讀取操作,而Undo Log是需要進行隨機讀寫的,所以我們有條件的話可以把Undo Log放在ssd這種隨機讀寫性能高的磁盤上以提高性能

查看重做日誌緩沖區大小,單位為字節:
技術分享圖片

重做日誌文件的數量由innodb_log_files_in_group參數決定:
技術分享圖片

特性二:

Innodb支持行級鎖,行級鎖是在寫操作時,我們所需要鎖定的資源更少,這樣我們支持的並發就會更多。需要註意的是Innodb的行級鎖是由存儲引擎層實現的,MySQL服務層是完全不了解存儲引擎中鎖的實現方式的。

什麽是鎖:鎖是數據庫系統區別於文件系統的重要特性,鎖的作用主要是管理共享資源的並發訪問。例如鎖可以控制當一個用戶向郵箱中投遞郵件的時候,另一個用戶會阻塞,無法向相同的郵件末尾寫入郵件,這樣就不會導致郵件的內容出現混淆。鎖的另一個特性就是實現事務的隔離性,對於未提交的事物,鎖定的數據,是無法被其他事務所查詢到的。

鎖的常見分類:共享鎖(也稱讀鎖),獨占鎖(也稱寫鎖),從名字中可以看出讀鎖是共享的,也就是說相互不會被阻塞的,多個線程可以在同一時間讀取同一資源,而不相互幹擾。寫鎖是獨占的,也就是排他的,一個寫鎖會阻塞其他的寫鎖或讀鎖。這是處於數據完整性的考慮,只有這樣才能保證,在給定的時間裏,只有一個線程能執行寫入,並防止其他用戶讀取正在寫入的同一資源,也就是前面所說的實現了事務的隔離性。

寫鎖與讀鎖的兼容關系如下表:
寫鎖 讀鎖
寫鎖 不兼容 不兼容
讀鎖 不兼容 兼容

寫鎖不兼容寫鎖和讀鎖,而讀鎖兼容讀鎖。需要註意的是,對Innodb來說讀鎖和寫鎖都是行鎖,所謂兼容性是指同一行記錄的兼容性情況。另外一點,實際上在Innodb裏鎖的兼容關系並不是如此,由於Innodb實現的鎖利用了Undo Log,所以實際使用時讀鎖和寫鎖是兼容的。

關於鎖的粒度含義:

鎖的粒度含義,就是如果加鎖資源的最小單位,比如在行上加鎖,最小單位就是行,這個鎖就稱為行級鎖。如果鎖的最小單位是數據頁,我們就稱為頁級鎖。同理如果鎖的最小單位是表的話,這個鎖就是表級鎖。通常提高共享資源並發性的方式就是讓鎖定義的對象盡可能的小,最理想的方式就是對修改的數據進行精確的鎖定。任何時候在給定的資源上鎖定的數據越少,系統的並發性就會越高,只要相互之間不產生阻塞就可以

mysql所支持的兩種鎖的粒度,表級鎖和行級鎖:

表級鎖開銷小,並發性低,表鎖會在加鎖時候鎖定整張表,當用戶對表進行寫操作的時候,要先進行解鎖,這時候就會阻塞其他用戶對表的讀寫操作,只有沒有寫鎖的時候,其他讀取的用戶才能獲得讀鎖,讀鎖之前說的是不會相互堵塞的,表級鎖通常是在mysql服務器層所實現的。

行級鎖可以最大程度的支持並發處理,同時鎖的開銷也比表級鎖開銷要大,所以它是並發性高,Innodb實現了行級鎖,行級鎖是在mysql存儲引擎中實現的,而不在mysql服務器中實現,

鎖的另外兩個概念,阻塞和死鎖:

阻塞是因為不同鎖之間兼容性的關系,在有些時刻,一個事務的鎖在需要等待另一個事務釋放它所占用的資源,這就形成了阻塞。比如前面所提到的表級鎖,如果當第一個連接,在一張Innodb表上加了排他鎖,此時第二個連接想要在該表上加共享鎖的話,就要等第一個連接釋放排他鎖,這樣第一個連接就阻塞了第二個連接。阻塞是為了確保事務可以並發且可以正常的運行。但是如果一個系統出現大量的阻塞就說明系統出現了問題,也許是在一個被頻繁更新的表上出現了慢查詢,或是一個頻繁訪問的資源加上了排他鎖。阻塞過多的時候可會令數據庫連接大量的堆積,從而占用大量的系統資源,使得系統性能整體下降。

死鎖是兩個或兩個以上事務在執行過程中,相互占用了對方等待的資源而產生的異常。從定義中可以看到,處在阻塞中的多個事務,阻塞事務占用了被等待阻塞事務的資源。而死鎖呢,則是多個事務,相互之間互相占用對方等待的資源,這是阻塞和死鎖的最大不同之處。另外一個不同點就是死鎖數據庫會自動發現,並且在多個死鎖的事務中,找到一個資源占用最少的事務來進行回滾操作,這樣就可以是其他事務正常運行了。所以說死鎖是可以由系統自動處理的,如果只有少量的死鎖並不會對系統造成什麽樣的影響,只要在應用程序中發現死鎖並進行處理就可以。但是如果一個系統頻繁的出現大量的死鎖就需要留意了,大多數情況下可以通過在多個事務中按相同順序訪問所需要資源來解決死鎖問題,也可以通過增加相關索引來解決。

關於鎖的一些實際操作,可以參考我早期寫的兩篇文章:

  • MySQL-鎖
  • MySQL-鎖02

Innodb引擎與其他大部分引擎不同的是,Innodb還提供了一個狀態監查監控工具,我們可以使用如下SQL語句查看監控信息:

show engine innodb status;

註:兩次采樣之間至少間隔30s,這樣才能保證采集到足夠的數據

執行該命令,輸出的內容大致如下,不同的版本可能輸出的內容不太一樣,我這裏使用的是5.7.18版本:


=====================================
2018-10-10 11:59:55 0x7f755c9c5700 INNODB MONITOR OUTPUT # 當前日期和時間
=====================================
Per second averages calculated from the last 57 seconds  # 這行顯示的是計算出這一平均值的時間間隔,即自上次輸出以來的時間,或者是距上次內部復位的時長
-----------------
BACKGROUND THREAD  # backgroup 線程信息
-----------------
srv_master_thread loops: 61445 srv_active, 0 srv_shutdown, 5196496 srv_idle
srv_master_thread log flush and writes: 5257941
----------
SEMAPHORES  # 如果有高並發的工作負載,你就要關註下接下來的段(SEMAPHORES信號量),它包含了兩種數據:事件計數器以及可選的當前等待線程的列表,如果有性能上的瓶頸,可以使用這些信息來找出瓶頸,不幸的是,想知道怎麽使用這些信息還是有一點復雜
----------
OS WAIT ARRAY INFO: reservation count 219819 # 這行給出了關於操作系統等待數組的信息,它是一個插槽數組,innodb在數組裏為信號量保留了一些插槽,操作系統用這些信號量給線程發送信號,使線程可以繼續運行,以完成它們等著做的事情,這一行還顯示出innodb使用了多少次操作系統的等待:保留統計(reservation count)顯示了innodb分配插槽的頻度,而信號計數(signal count)衡量的是線程通過數組得到信號的頻度,操作系統的等待相對於空轉等待(spin wait)要昂貴些。
OS WAIT ARRAY INFO: signal count 219805  # 進行OS WAIT線程,接收到多少次信號(single)被喚醒,如果這個single數值越大,幾十萬或者幾百萬,可能是很多I/0等待或者是InnoDB爭用問題(關於爭用問題可能與OS調度有關,可以嘗試減少innodb_thread_concurrency參數)
RW-shared spins 0, rounds 168443, OS waits 84271  # RW-shared 共享鎖,
RW-excl spins 0, rounds 180120, OS waits 1119  # RW-excl 排他鎖
RW-sx spins 60, rounds 6000, OS waits 50
Spin rounds per wait: 168443.00 RW-shared, 180120.00 RW-excl, 100.00 RW-sx
------------
TRANSACTIONS  # 包含了InnoDB事務(transaction)的統計信息
------------
Trx id counter 264168  # 當前的transaction id ,這是個系統變量,隨著每次新的transaction產生而增加
Purge done for trx‘s n:o < 264167 undo n:o < 0 state: running but idle  # 正在進行清空的操作操作的transaction ID,Purge的原則就是記錄沒有被其它事務繼續使用了
History list length 10  # 記錄了undo spaces 內unpurged 的事務個數
LIST OF TRANSACTIONS FOR EACH SESSION:   # 當前活躍事務列表
---TRANSACTION 421617178700976, not started  # 每個事務的第一行以事務的ID和狀態開始,not started表示這個事務已經提交並且沒有再發起影響事務的語句,可能剛好空閑
0 lock struct(s), heap size 1136, 0 row lock(s) # 該事務鎖定結構的數目和堆大小以及鎖定的行數,堆的大小指的是為了持有這些行鎖而占用的內存大小
---TRANSACTION 421617178702800, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178697328, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178701888, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178700064, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178699152, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178698240, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178695504, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178704624, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421617178696416, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O  # 顯示了I/O  Helper thread d的狀態,包含一些統計信息
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread) # insert buffer thread
I/O thread 1 state: waiting for i/o request (log thread) # log thread
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread) # 以上為默認的4個read thread
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread) # 以上為默認的4個write thread
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,  # 讀線程和寫線程掛起操作的數目等,aio的意思是異步I/O
 ibuf aio reads:, log i/o‘s:, sync i/o‘s:   # insert buffer thread掛起的fsync()操作數目等
Pending flushes (fsync) log: 0; buffer pool: 0  # log thread掛起的fsync()操作數目等
469 OS file reads, 1083592 OS file writes, 570823 OS fsyncs  # 這行顯示了讀,寫和fsync()調用執行的數目,在你的機器環境負載下這些絕對值可能會有所不同,因此更重要的是監控它們過去一段時間內是如何改變的
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s  # 這行顯示了當前被掛起的讀和寫操作數

註:三行掛起讀寫線程、緩沖池線程、日誌線程的統計信息的值是檢測I/O受限的應用的一個好方法,如果這些I/O大部分有掛起操作,那麽負載可能I/O受限。在linux系統下使用參數:innodb_read_io_threads和innodb_write_io_threads兩個變量來配置讀寫線程的數量,默認為各4個線程。
insert buffer thread:負責插入緩沖合並,如:記錄被從插入緩沖合並到表空間中
log thread:負責異步刷事務日誌
read thread:執行預讀操作以嘗試預先讀取innodb預感需要的數據
write thread:刷新臟頁緩沖

-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX  # 這部分顯示了insert buffer和adaptive hash index兩個部分的結構的狀態
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges  # 這行顯示了關於size(size 12代表了已經合並記錄頁的數量)、free list(代表了插入緩沖中空閑列表長度)和seg size大小(seg size 27572顯示了當前insert buffer的長度,大小為27572*16K=440M左右)的信息。18074934 merges代表合並插入的次數
merged operations:  # 這個標簽下的一行信息insert,delete mark,delete分別表示merge操作合並了多少個insert buffer,delete buffer,purge buffer
 insert 0, delete mark 0, delete 0  # insert 插入的記錄數,delete mark 打上的標記,delete 刪除的次數
discarded operations:   # 這個標簽下的一行信息表示當change buffer發生merge時表已經被刪除了,就不需要再將記錄合並到輔助索引中了
 insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 13 buffer(s)  # 這行顯示了自使用哈希索引的狀態,其中,Hash table size 87709057表示AHI的大小,node heap has 10228 buffer(s)表示AHI的使用情況
Hash table size 34679, node heap has 8 buffer(s)
Hash table size 34679, node heap has 4 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 4 buffer(s)
Hash table size 34679, node heap has 13 buffer(s)
Hash table size 34679, node heap has 14 buffer(s)
Hash table size 34679, node heap has 2 buffer(s)
11.61 hash searches/s, 0.00 non-hash searches/s   # 這行顯示了在頭部第1部分提及的時間內Innodb每秒完成了多少哈希索引操作,1741.05 hash searches/s表示每秒使用AHI搜索的情況,539.48 non-hash searches/s表示每秒沒有使用AHI搜索的情況(因為哈希索引只能用於等值查詢,而範圍查詢,模糊查詢是不能使用哈希索引的。),通過hash searches: non-hash searches的比例大概可以了解使用哈希索引後的效率,哈希索引查找與非哈希索引查找的比例僅供參考,自適應哈希索引無法配置,但是可以通過innodb_adaptive_hash_index=ON|OFF參數來選擇是否需要這個特性。
---
LOG  # 這部分顯示了關於innodb事務日誌(重做日誌)子系統的統計
---
Log sequence number 113764958  # 這行顯示了當前最新數據產生的日誌序列號
Log flushed up to   113764958  # 這行顯示了日誌已經刷新到哪個位置了(已經落盤到事務日誌中的日誌序列號)
Pages flushed up to 113764958  
Last checkpoint at  113764949  # 這行顯示了上一次檢查點的位置(一個檢查點表示一個數據和日誌文件都處於一致狀態的時刻,並且能用於恢復數據),如果上一次檢查點落後與上一行太多,並且差異接近於事務日誌文件的大小,Innodb會觸發“瘋狂刷”,這對性能而言非常糟糕。
0 pending log flushes, 0 pending chkp writes  # 這行顯示了當前掛起的日誌讀寫操作,可以將這行的值與第7部分FILE I/O對應的值做比較,以了解你的I/O有多少是由於日誌系統引起的。
350037 log i/o‘s done, 0.00 log i/o‘s/second  # 這行顯示了日誌操作的統計和每秒日誌I/O數,可以將這行的值與第7部分FILE I/O對應的值做比較,以了解你的I/O有多少是由於日誌系統引起的。
---------------------- 
BUFFER POOL AND MEMORY  # 這部分顯示了關於innodb緩沖池及其如何使用內存的統計
----------------------
Total large memory allocated 137428992  # 這行顯示了由innodb分配的總內存,以及其中多少是額外內存池分配,額外內存池僅分配了其中很小一部分內存,由內部內存分配器分配,現在的innodb版本一般使用操作系統的內存分配器,但老版本使用自己的,這是由於在那個時代有些操作系統並未提供一個非常好的內存分配實現。
Dictionary memory allocated 1401012
Buffer pool size   8192  # 從這行開始的下面4行顯示緩沖池度量值,以頁為單位,度量值有總的緩沖池大小,空閑頁數,分配用來存儲數據庫頁的頁數,以及臟數據庫頁數。這行顯示了緩沖池總共有多少個頁,即即2705015*16K,共有43G的緩沖池
Free buffers       6147  # 這行顯示了緩沖池空閑頁數
Database pages     1986  # 這行顯示了分配用來存儲數據庫頁的頁數,即,表示LRU列表中頁的數量,包含young sublist和old sublist
Old database pages 713   # 這行顯示了LRU中的old sublist部分頁的數量
Modified db pages  0     # 這行顯示臟數據庫頁數
Pending reads      0     # 這行顯示了掛起讀的數量
Pending writes: LRU 0, flush list 0, single page 0  # 這行顯示了掛起寫的數量
# 註意,這裏掛起的讀和寫操作並不與FILE I/O部分的值匹配,因為Innodb可能合並許多的邏輯讀寫操作到一個物理I/O操作中,LRU代表最近使用到的被掛起數量,它是通過沖刷緩沖中不經常使用的頁來釋放空間以供給經常使用的頁的一種方法,沖刷列表flush list存放著檢查點處理需要沖刷的舊頁被掛起的數量,單頁single page被掛起的數量(single page寫是獨立的頁面寫,不會被合並)。
Pages made young 0, not young 0   # 這行顯示了LRU列表中頁移動到LRU首部的次數,因為該服務器在運行階段改變沒有達到innodb_old_blocks_time閥值的值,因此not young為0
0.00 youngs/s, 0.00 non-youngs/s  # 表示每秒young和non-youngs這兩類操作的次數
Pages read 428, created 1558, written 680621  # 這行顯示了innodb被讀取,創建,寫入了多少頁,讀/寫頁的值是指的從磁盤讀到緩沖池的數據,或者從緩沖池寫到磁盤中的數據,創建頁指的是innodb在緩沖池中分配但沒有從數據文件中讀取內容的頁,因為它並不關心內容是什麽(如,它們可能屬於一個已經被刪除的表)
0.00 reads/s, 0.00 creates/s, 0.00 writes/s  # 這行顯示了對應上面一行的每秒read,create,write的頁數
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000  # 這行顯示了緩沖池的命中率,它用來衡量innodb在緩沖池中查找到所需頁的比例,它度量自上次Innodb狀態輸出後到本次輸出這段時間內的命中率,因此,如果服務器自那以後一直很安靜,你將會看到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: 1986, unzip_LRU len: 0   # innodb1.0.x開始支持壓縮頁的功能,將原來16K的頁壓縮為1K,2K,4K,8K,而由於頁的大小發生了變化,LRU列表也有了些改變,對於非16K的頁,是通過unzip_LRU列表進行管理的,可以看到unzip_LRU len為0表示沒有使用壓縮頁.
I/O sum[0]:cur[0], unzip sum[0]:cur[0]  # 統計信息及解壓信息
--------------
ROW OPERATIONS  # 這部分顯示了其他各項的innodb統計
--------------
0 queries inside InnoDB, 0 queries in queue  # 這行顯示了innodb內核內有多少個線程,隊列中有多少個線程,隊列中的查詢是innodb為限制並發執行的線程數量而不運行進入內核的線程。查詢在進入隊列之前會休眠等待。
0 read views open inside InnoDB  # 這行顯示了有多少打開的innodb讀視圖,讀視圖是包含事務開始點的數據庫內容的MVCC快照,你可以看看某特定事務在第6部分TRANSACTIONS是否有讀視圖
Process ID=32728, Main thread ID=140141416933120, state: sleeping  # 這行顯示了內核的主線程狀態
Number of rows inserted 115492, updated 164886, deleted 1698, read 1351954675  # 這行顯示了多少行被插入,更新和刪除,讀取
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 34.46 reads/s  # 這行顯示了對應上面一行的每秒平均值,如果想查看innodb有多少工作量在進行,那麽這兩行是很好的參考值
----------------------------
END OF INNODB MONITOR OUTPUT  # 信息結束標記,要註意了,如果看不到這行輸出,可能是有大量事務或者是有一個大的死鎖截斷了輸出信息
============================

MySQL自身對性能的影響