溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

show engine innodb status解讀

發(fā)布時(shí)間:2020-08-09 18:32:54 來源:ITPUB博客 閱讀:286 作者:steven_hua 欄目:MySQL數(shù)據(jù)庫

show engine innodb status解讀



注:以下內(nèi)容為根據(jù)《高性能mysql第三版》和《mysql技術(shù)內(nèi)幕innodb存儲引擎》的innodb status部分的個(gè)人理解,如果有錯(cuò)誤,還望指正??!

  innodb存儲引擎在show engine innodb status(老版本對應(yīng)的是show innodb status)輸出中,顯示除了大量的內(nèi)部信息,它輸出就是一個(gè)單獨(dú)的字符串,沒有行和列,內(nèi)容分為很多小段,每一段對應(yīng)innodb存儲引擎不同部分的信息,其中有一些信息對于innodb開發(fā)者來說非常有用,但是,許多信息,如果你嘗試去理解,并且應(yīng)用到高性能innodb調(diào)優(yōu)的時(shí)候,你會發(fā)現(xiàn)它們非常有趣,甚至是非常有必要的。

輸出內(nèi)容中包含了一些平均值的統(tǒng)計(jì)信息,這些平均值是自上次輸出結(jié)果生成以來的統(tǒng)計(jì)數(shù),因此,如果你正在檢查這些值,那就要確保已經(jīng)等待了至少30s的時(shí)間,使兩次采樣之間的積累足夠長的統(tǒng)計(jì)時(shí)間并多次采樣,檢查計(jì)數(shù)器變化從而弄清其行為,并不是所有的輸出都會在一個(gè)時(shí)間點(diǎn)上生成,因而也不是所有的顯示出來的平均值會在同一時(shí)間間隔里重新再計(jì)算。而且,innodb有一個(gè)內(nèi)部復(fù)位間隔,而它是不可預(yù)知的,各個(gè)版本也不一樣。

這些輸出信息足夠提供給手工計(jì)算出大多數(shù)你想要的統(tǒng)計(jì)信息,有一款監(jiān)控工具innotop可以幫你計(jì)算出增量差值和平均值。下面,在你的mysql命令行敲下show engine innodb status;看著輸出跟著下面的步驟一步一步理解輸出信息是什么含義:

注意:以下使用mysql5.5.24版本做解讀,mysql5.6.x和5.7.x輸出內(nèi)容有些地方有調(diào)整。

1.第一段是頭部信息,它僅僅聲明了輸出的開始,其內(nèi)容包括當(dāng)前的日期和時(shí)間,以及自上次輸出以來經(jīng)過的時(shí)長。

=====================================
160129 12:07:26 INNODB MONITOR OUTPUT #第二行是當(dāng)前日期和時(shí)間
=====================================
Per second averages calculated from the last 24 seconds #第四行顯示的是計(jì)算出這一平均值的時(shí)間間隔,即自上次輸出以來的時(shí)間,或者是距上次內(nèi)部復(fù)位的時(shí)長



2.從innodb1.0.x開始,可以使用命令show engine innodb status;來查看master thread的狀態(tài)信息:

-----------------
BACKGROUND THREAD
-----------------

srv_master_thread loops: 30977173 1_second, 30975685 sleeps, 3090359 10_second, 166112 background, 165988 flush #這行顯示主循環(huán)進(jìn)行了30977173 1_second次,每秒掛起的操作進(jìn)行了30975685 sleeps次(說明負(fù)載不是很大),10秒一次的活動進(jìn)行了3090359 10_second次,1秒循環(huán)和10秒循環(huán)比值符合1:10,backgroup loop進(jìn)行了166112 background次,flush loop進(jìn)行了165988 flush次,如果在一臺很大壓力的mysql上,可能看到每秒運(yùn)行次數(shù)和掛起次數(shù)比例小于1很多,這是因?yàn)閕nnodb對內(nèi)部進(jìn)行了一些優(yōu)化,當(dāng)壓力大時(shí)間隔時(shí)間并不總是等待1秒,因此,不能認(rèn)為每秒循環(huán)和掛起的值總是相等,在某些情況下,可以通過兩者之間的差值來比較反映當(dāng)前數(shù)據(jù)庫的負(fù)載壓力。

srv_master_thread log flush and writes: 31160103



3.如果有高并發(fā)的工作負(fù)載,你就要關(guān)注下接下來的段(SEMAPHORES信號量),它包含了兩種數(shù)據(jù):事件計(jì)數(shù)器以及可選的當(dāng)前等待線程的列表,如果有性能上的瓶頸,可以使用這些信息來找出瓶頸,不幸的是,想知道怎么使用這些信息還是有一點(diǎn)復(fù)雜,下面先給出一些解釋:

----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 68581015, signal count 218437328 
--Thread 140653057947392 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff536c7d3c0 created in file buf0buf.c line 916
a writer (thread id 140653057947392) has reserved it in mode exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
--Thread 140653677291264 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff53945b240 created in file buf0buf.c line 916
a writer (thread id 140653677291264) has reserved it in mode exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
Mutex spin waits 1157217380, rounds 1783981614, OS waits 10610359
RW-shared spins 103830012, rounds 1982690277, OS waits 52051891
RW-excl spins 43730722, rounds 602114981, OS waits 3495769
Spin rounds per wait: 1.54 mutex, 19.10 RW-shared, 13.77 RW-excl


內(nèi)容比較多,下面分段依次解釋:
3.1.
OS WAIT ARRAY INFO: reservation count 68581015, signal count 218437328 #這行給出了關(guān)于操作系統(tǒng)等待數(shù)組的信息,它是一個(gè)插槽數(shù)組,innodb在數(shù)組里為信號量保留了一些插槽,操作系統(tǒng)用這些信號量給線程發(fā)送信號,使線程可以繼續(xù)運(yùn)行,以完成它們等著做的事情,這一行還顯示出innodb使用了多少次操作系統(tǒng)的等待:保留統(tǒng)計(jì)(reservation count)顯示了innodb分配插槽的頻度,而信號計(jì)數(shù)(signal count)衡量的是線程通過數(shù)組得到信號的頻度,操作系統(tǒng)的等待相對于空轉(zhuǎn)等待(spin wait)要昂貴些。


3.2.

--Thread 140653057947392 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff536c7d3c0 created in file buf0buf.c line 916
a writer (thread id 140653057947392) has reserved it in mode exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
--Thread 140653677291264 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff53945b240 created in file buf0buf.c line 916
a writer (thread id 140653677291264) has reserved it in mode exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
這部分顯示的是當(dāng)前正在等待互斥量的innodb線程,在這里可以看到有兩個(gè)線程正在等待,每一個(gè)都是以--Thread <數(shù)字> has waited...開始,這一段內(nèi)容在正常情況下應(yīng)該是空的(即查看的時(shí)候沒有這部分內(nèi)容),除非服務(wù)器運(yùn)行著高并發(fā)的工作負(fù)載,促使innodb采取讓操作系統(tǒng)等待的措施,除非你對innodb源碼熟悉,否則這里看到的最有用的信息就是發(fā)生線程等待的代碼文件名 /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151。


在innodb內(nèi)部哪里才是熱點(diǎn)?舉例來說,如果看到許多線程都在一個(gè)名為buf0buf.c的文件上等待,那就意味著你的系統(tǒng)里存在著
緩沖池競爭,這個(gè)輸出信息還顯示了這些線程等待了多少時(shí)間,其中waiters flag顯示了有多少個(gè)等待著正在等待同一個(gè)互斥量。 如果waiters flag為0那就表示沒有線程在等待同一個(gè)互斥量(此時(shí)在waiters flag 0后面可能可以看到wait is ending,表示這個(gè)互斥量已經(jīng)被釋放了,但操作系統(tǒng)還沒有把線程調(diào)度過來運(yùn)行)。

你可能想知道innodb真正等待的是什么,innodb使用了互斥量和信號量來保護(hù)代碼的臨界區(qū),如:限定每次只能有一個(gè)線程進(jìn)入臨界區(qū),或者是當(dāng)有活動的讀時(shí),就限制寫入等。在innodb代碼里有很多臨界區(qū),在合適的條件下,它們都可能出現(xiàn)在那里,常常能見到的一種情形是:獲取緩沖池分頁的訪問權(quán)的時(shí)候。

3.3.
在等待線程之后的部分信息如下,這部分顯示了更多的事件計(jì)數(shù)器,在每一個(gè)情形中,都能看到innodb依靠操作系統(tǒng)等待的頻度:

Mutex spin waits 1157217380, rounds 1783981614, OS waits 10610359 #這行顯示的是跟互斥量相關(guān)的幾個(gè)計(jì)數(shù)器
RW-shared spins 103830012, rounds 1982690277, OS waits 52051891 #這行顯示讀寫的共享鎖的計(jì)數(shù)器
RW-excl spins 43730722, rounds 602114981, OS waits 3495769 #這行顯示讀寫的排他鎖的計(jì)數(shù)器
Spin rounds per wait: 1.54 mutex, 19.10 RW-shared, 13.77 RW-excl

innodb有著一個(gè)多階段等待的策略,首先,它會試著對鎖進(jìn)行空轉(zhuǎn)等待,如果經(jīng)歷了一個(gè)預(yù)設(shè)的空轉(zhuǎn)等待周期(設(shè)置innodb_sync_spin_loops配置變量命令)之后還沒有成功,那就會退到更昂貴更復(fù)雜的等待數(shù)組中。
空轉(zhuǎn)等待的成本相對較低,但是它們要不停地檢查一個(gè)資源能否被鎖定,這種方式會消耗CPU周期,但是,這沒有聽起來那么糟糕,因?yàn)楫?dāng)處理器在等待IO時(shí),一般都有一些空閑的CPU周期可用,即使是沒有空閑的CPU周期,空等也要比其他方式更加廉價(jià)一些。然而,當(dāng)另外一個(gè)線程能做一些事情的時(shí)候,空轉(zhuǎn)等待也還會把CPU獨(dú)占著。
空轉(zhuǎn)等待的替代方案就是讓操作系統(tǒng)做上下文切換,這樣,當(dāng)一個(gè)線程在等待時(shí),另外一個(gè)線程就可以被運(yùn)行,然后,通過等待數(shù)組里的信號量發(fā)出信號,喚醒那個(gè)沉睡的線程,通過信號量來發(fā)送信號是比較有效的,但是上下文切換就很昂貴,這很快就會積少成多,每秒鐘幾千次的切換會引發(fā)大量的系統(tǒng)開銷。
你可以通過修改innodb_sync_spin_loops的值,試著在空轉(zhuǎn)等待與操作系統(tǒng)等待之間達(dá)成平衡,不要擔(dān)心空轉(zhuǎn)等待,除非你在一秒里看到幾十萬個(gè)空轉(zhuǎn)等待。此時(shí),你可以考慮performance_schema庫或者show engine innodb mutex;查看下相關(guān)信息。


4.下面這一段外鍵錯(cuò)誤的信息一般不會出現(xiàn),除非你服務(wù)器上發(fā)生了外鍵錯(cuò)誤,有時(shí)問題在于事務(wù)在插入,更新或刪除一條記錄時(shí)要尋找父表或子表,還有時(shí)候是當(dāng)innodb嘗試增加或刪除一個(gè)外鍵或者修改一個(gè)已經(jīng)存在的外鍵時(shí),發(fā)現(xiàn)表之間類型不匹配,這部分輸出對于調(diào)試與innodb不明確的外鍵錯(cuò)誤發(fā)生的準(zhǔn)確原因非常有幫助,下面搞一個(gè)示例來看看:

4.1 創(chuàng)建父表:
mysql> create table parent(parent_id int not null,primary key(parent_id)) engine=innodb;

4.2 創(chuàng)建子表:
mysql> create table child(child_id int not null,key child_id(child_id),constraint i_child foreign key(child_id) references parent(parent_id)) engine=innodb;

4.3 插入數(shù)據(jù):
mysql> insert into parent(parent_id) values(1);
mysql> insert into child(child_id) values(1);

4.5 有兩種基本的外鍵錯(cuò)誤:
第一種:以某種可能違反外鍵約束關(guān)系的方法增加,更新,刪除數(shù)據(jù),將導(dǎo)致第一類錯(cuò)誤,如,在父表中刪除行時(shí)發(fā)生如下錯(cuò)誤:

mysql> delete from parent;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`xiaoboluo`.`child`, CONSTRAINT `i_child` FOREIGN KEY (`child_id`) REFERENCES `parent` (`parent_id`))


錯(cuò)誤信息相當(dāng)明了,對所有由增加,刪除,更新不匹配的行導(dǎo)致的錯(cuò)誤都會看到相似的信息,下面是show engine innodb status的輸出:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
160128 1:17:06 Transaction: #這行顯示了最近一次外鍵錯(cuò)誤的日期和時(shí)間
TRANSACTION D203D6, ACTIVE 0 sec updating or deleting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 1
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1813996 localhost root updating
delete from parent
Foreign key constraint fails for table `xiaoboluo`.`child`:
, #上面部分顯示了關(guān)于破壞外鍵約束的事務(wù)詳情。后邊部分顯示了發(fā)現(xiàn)錯(cuò)誤時(shí)innodb正嘗試修改的準(zhǔn)確數(shù)據(jù),輸出中有許多是轉(zhuǎn)換成可打印格式的行數(shù)據(jù)
CONSTRAINT `i_child` FOREIGN KEY (`child_id`) REFERENCES `parent` (`parent_id`)
Trying to delete or update in parent table, in index `PRIMARY` tuple:
DATA TUPLE: 3 fields;
0: len 4; hex 80000001; asc ;;
1: len 6; hex 000000d203d6; asc ;;
2: len 7; hex 1e000001ca0110; asc ;;

But in child table `xiaoboluo`.`child`, in index `child_id`, there is a record:
PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 80000001; asc ;;
1: len 6; hex 000013a99b3e; asc >;;


4.6 第二種:嘗試修改父表的表結(jié)構(gòu)時(shí)發(fā)生的錯(cuò)誤,這種錯(cuò)誤就沒有那么清楚了,這可能會讓調(diào)試更困難:

mysql> alter table parent modify parent_id int unsigned not null;
ERROR 1025 (HY000): Error on rename of './xiaoboluo/#sql-b695_4e3b' to './xiaoboluo/parent' (errno: 150)

查看show engine innodb status輸出信息:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
160128 1:32:33 Error in foreign key constraint of table xiaoboluo/child:
there is no index in referenced table which would contain
the columns as the first columns, or the data types in the
referenced table do not match the ones in table. Constraint:
,
CONSTRAINT "i_child" FOREIGN KEY ("child_id") REFERENCES "parent" ("parent_id")
The index in the foreign key in table is "child_id"
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
InnoDB: Renaming table `xiaoboluo`.<result 2 when explaining filename '#sql-b695_4e3b'> to `xiaoboluo`.`parent` failed!


上面的錯(cuò)誤是數(shù)據(jù)類型不匹配,外鍵列必須有完全相同的數(shù)據(jù)類型,包括任何的修飾符(如這里父表多加了一個(gè)unsigned,這也是問題所在),當(dāng)看到1025錯(cuò)誤并不理解為什么時(shí),最好查看下innodb status。在每次看到有新錯(cuò)誤時(shí),外鍵錯(cuò)誤信息都會被重寫,percona toolkit中的pt-fk-error-logger工具可以用表保存這些信息以供后續(xù)分析。


5.與外鍵錯(cuò)誤一樣,這部分只有當(dāng)服務(wù)器產(chǎn)生死鎖時(shí)才會出現(xiàn),死鎖信息同樣在每次有新的死鎖錯(cuò)誤時(shí)被重寫,percona toolkit中的pt-deadlock-logger工具可以用表保存這些信息以供后續(xù)分析
死鎖在等待關(guān)系圖里是一個(gè)循環(huán),就是一個(gè)鎖定了行的數(shù)據(jù)結(jié)構(gòu)又在等待別的鎖,這個(gè)循環(huán)可以任意地大,innodb會立即檢測到死鎖,因?yàn)槊慨?dāng)有事務(wù)等待行鎖的時(shí)候,它都會去檢查等待關(guān)系圖里是否有循環(huán),死鎖的情況可能會比較復(fù)雜,但是,這一部分只顯示了最近的兩個(gè)死鎖的情況,它們在各自的事務(wù)里執(zhí)行的最后一條語句,以及它們在等待關(guān)系圖里形成環(huán)鎖的信息。在這個(gè)循環(huán)里你看不到其他事務(wù),也可能看不到在事務(wù)里早先真正獲得了鎖的語句,盡管如此,通常還是可以通過查看這些輸出結(jié)果來確定到底是什么引起了死鎖。

在innodb里實(shí)際上有兩種死鎖,第一種就是常常碰到的那種,它在等待關(guān)系圖里是一個(gè)真正的循環(huán),另外一種就是在一個(gè)等待關(guān)系圖里,因代價(jià)昂貴而無法檢測它是不是包含了循環(huán),如果innodb要在關(guān)系圖里檢查超過100W個(gè)鎖,或者在檢查過程中,innodb要重做200個(gè)以上的事務(wù),那它會放棄,并宣布這里有一個(gè)死鎖,這些數(shù)值都是硬編碼在innodb代碼里的常量,無法配置(如果你NB可以修改代碼然后重新編譯)。第二種死鎖報(bào)錯(cuò)你可以在輸出里看到一條信息:TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH


innodb不僅會打印出事務(wù)和事務(wù)持有和等待的鎖,而且還有記錄本身,不幸的是,它至于可能超過為輸出結(jié)果預(yù)留的長度(只能打印1M的內(nèi)容且只能保留最近一次的死鎖信息),如果你無法看到完整的輸出,此時(shí)可以在任意庫下創(chuàng)建innodb_monitor或innodb_lock_monitor表,這樣innodb status信息會完整且每15s一次被記錄到錯(cuò)誤日志中。如:create table innodb_monitor(a int)engine=innodb;,不需要記錄到錯(cuò)誤日志中時(shí)就刪掉這個(gè)表即可。



5.1 下面也搞一個(gè)示例來看看:

5.1.1 建表:

mysql> create table test_deadlock(id int unsigned not null primary key auto_increment,test int unsigned not null);
Query OK, 0 rows affected (0.02 sec)

5.1.2 插入測試數(shù)據(jù):
mysql> insert into test_deadlock(test) values(1),(2),(3),(4),(5);
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0


打開兩個(gè)會話終端:
5.1.3 會話1執(zhí)行下面的SQL:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_deadlock where id=1 for update;
+----+------+
| id | test |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.00 sec)

5.1.4 接著會話2執(zhí)行下面的SQL:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_deadlock where id=2 for update;
+----+------+
| id | test |
+----+------+
| 2 | 2 |
+----+------+
1 row in set (0.00 sec)


5.1.5 回到會話1執(zhí)行下面的SQL,會發(fā)生等待:

mysql> select * from test_deadlock where id=2 for update;


5.1.6 回到會話2執(zhí)行下面的SQL,產(chǎn)生死鎖,會話2被回滾:

mysql> select * from test_deadlock where id=1 for update;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

5.2 查看innodb status信息:

------------------------
LATEST DETECTED DEADLOCK
------------------------
160128 1:51:53 #這里顯示了最近一次發(fā)生死鎖的日期和時(shí)間
*** (1) TRANSACTION:
TRANSACTION D20847, ACTIVE 141 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1818124 localhost root statistics
select * from test_deadlock where id=2 for update
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20847 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 00000002; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab011d; asc ;;
3: len 4; hex 00000002; asc ;;

*** (2) TRANSACTION:
TRANSACTION D20853, ACTIVE 119 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1248, 2 row lock(s)
MySQL thread id 20081, OS thread handle 0x7f0a0f020700, query id 1818204 localhost root statistics
select * from test_deadlock where id=1 for update
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 00000002; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab011d; asc ;;
3: len 4; hex 00000002; asc ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 00000001; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab0110; asc ;;
3: len 4; hex 00000001; asc ;;

*** WE ROLL BACK TRANSACTION (2)


這部分內(nèi)容比較多,下面分段逐一進(jìn)行解釋:
5.2.1 下面這部分顯示的是死鎖的第一個(gè)事務(wù)的信息:

*** (1) TRANSACTION:
TRANSACTION D20847, ACTIVE 141 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1818124 localhost root statistics
select * from test_deadlock where id=2 for update

TRANSACTION D20847, ACTIVE 141 sec starting index read:這行表示事務(wù)D20847,ACTIVE 141 sec表示事務(wù)處于活躍狀態(tài)141s,starting index read表示正在使用索引讀取數(shù)據(jù)行
mysql tables in use 1, locked 1#這行表示事務(wù)D20847正在使用1個(gè)表,且涉及鎖的表有1個(gè)
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s) #這行表示在等待3把鎖,占用內(nèi)存376字節(jié),涉及2行記錄,如果事務(wù)已經(jīng)鎖定了幾行數(shù)據(jù),這里將會有一行信息顯示出鎖定結(jié)構(gòu)的數(shù)目(注意,這跟行鎖是兩回事)和堆大小,堆的大小指的是為了持有這些行鎖而占用的內(nèi)存大小,Innodb是用一種特殊的位圖表來實(shí)現(xiàn)行鎖的,從理論上講,它可將每一個(gè)鎖定的行表示為一個(gè)比特,經(jīng)測試顯示,每個(gè)鎖通常不超過4比特
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1818124 localhost root statistics #這行表示該事務(wù)的線程ID信息,操作系統(tǒng)句柄信息,連接來源、用戶
select * from test_deadlock where id=2 for update #這行表示事務(wù)涉及的SQL


5.2.2 下面這一部分顯示的是當(dāng)死鎖發(fā)生時(shí),第一個(gè)事務(wù)正在等待的鎖等信息:

*** (1) WAITING FOR THIS LOCK TO BE GRANTED: #這行信息表示第一個(gè)事務(wù)正在等待鎖被授予
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20847 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 00000002; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab011d; asc ;;
3: len 4; hex 00000002; asc ;;

RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20847 lock_mode X locks rec but not gap waiting#這行信息表示等待的鎖是一個(gè)record lock,空間id是441,頁編號為3,大概位置在頁的72位處,鎖發(fā)生在表xiaoboluo.test_deadlock的主鍵上,是一個(gè)X鎖,但是不是gap lock。 waiting表示正在等待鎖
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 #這行表示record lock的heap no 位置

#這部分剩下的內(nèi)容只對調(diào)試才有用。

0: len 4; hex 00000002; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab011d; asc ;;
3: len 4; hex 00000002; asc ;;


5.2.3 下面這部分是事務(wù)二的狀態(tài):

*** (2) TRANSACTION:
TRANSACTION D20853, ACTIVE 119 sec starting index read #事務(wù)2處于活躍狀態(tài)119s
mysql tables in use 1, locked 1 #正在使用1個(gè)表,涉及鎖的表有1個(gè)
3 lock struct(s), heap size 1248, 2 row lock(s) #涉及3把鎖,2行記錄
MySQL thread id 20081, OS thread handle 0x7f0a0f020700, query id 1818204 localhost root statistics
select * from test_deadlock where id=1 for update #第二個(gè)事務(wù)的SQL

5.2.4 下面這部分是事務(wù)二的持有鎖信息:

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 00000002; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab011d; asc ;;
3: len 4; hex 00000002; asc ;;

RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 #從這兩行持有鎖信息計(jì)息后面幾行調(diào)試信息上看,就是事務(wù)1正在等待的鎖。

5.2.5 下面這部分是事務(wù)二正在等待的鎖,從下面的信息上看,等待的是同一個(gè)表,同一個(gè)索引,同一個(gè)page上的record lock X鎖,但是heap no位置不同,即不同的行上的鎖:

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 
0: len 4; hex 00000001; asc ;;
1: len 6; hex 000000d20808; asc ;;
2: len 7; hex ad000001ab0110; asc ;;
3: len 4; hex 00000001; asc ;;

*** WE ROLL BACK TRANSACTION (2) #這個(gè)表示事務(wù)2被回滾,因?yàn)閮蓚€(gè)事務(wù)的回滾開銷一樣,所以選擇了后提交的事務(wù)進(jìn)行回滾,如果兩個(gè)事務(wù)回滾的開銷不同(undo 數(shù)量不同),那么就回滾開銷最小的那個(gè)事務(wù)。

當(dāng)一個(gè)事務(wù)持有了其他事務(wù)需要的鎖,同時(shí)又想獲得其他事務(wù)持有的鎖時(shí),等待關(guān)系圖上就會產(chǎn)生循環(huán),Innodb不會顯示所有持有和等待的鎖,但是,它顯示了足夠的信息來幫你確定,查詢操作正在使用哪些索引,這對于你確定能否避免死鎖有極大的價(jià)值。

如果能使兩個(gè)查詢對同一個(gè)索引朝同一個(gè)方向進(jìn)行掃描,就能降低死鎖的數(shù)目,因?yàn)椋樵冊谕粋€(gè)順序上請求鎖的時(shí)候不會創(chuàng)建循環(huán),有時(shí)候,這是很容易做到的,如:要在一個(gè)事務(wù)里更新許多條記錄,就可以在應(yīng)用程序的內(nèi)存里把它們按照主鍵進(jìn)行排序,然后,再用同樣的順序更新到數(shù)據(jù)庫里,這樣就不會有死鎖發(fā)生,但是在另一些時(shí)候,這個(gè)方法也是行不通的(如果有兩個(gè)進(jìn)程使用了不同的索引區(qū)間操作同一張表的時(shí)候)。


6. 下面這部分包含了一些關(guān)于innodb事務(wù)的總結(jié)信息,緊隨其后的是當(dāng)前活躍事務(wù)列表,如:
------------

TRANSACTIONS
------------
Trx id counter 4E0132AD
Purge done for trx's n:o < 4E01090B undo n:o < 0
History list length 1853
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 4E0131D3, not started
MySQL thread id 26208218, OS thread handle 0x7fec7c582700, query id 5274800318 10.207.162.69 gdsser
---TRANSACTION 4E01323F, not started
MySQL thread id 26208217, OS thread handle 0x7fec7c1b3700, query id 5274800938 10.207.162.69 gdsser

....................
---TRANSACTION 4E0132AC, ACTIVE 0 sec preparing
2 lock struct(s), heap size 376, 1 row lock(s), undo log entries 1
MySQL thread id 26208200, OS thread handle 0x7fec567e0700, query id 5274801557 10.207.162.69 gdsser
commit
---TRANSACTION 4E0110E7, ACTIVE 188 sec
mysql tables in use 1, locked 0
MySQL thread id 26208154, OS thread handle 0x7fec7c235700, query id 5274800671 10.143.90.228 root Sending data
SELECT /*!40001 SQL_NO_CACHE */ * FROM `m_flowskillpoint`
Trx read view will not see trx with id >= 4E0110E8, sees < 4E0108EE
---TRANSACTION 4E0108EF, ACTIVE 233 sec fetching rows
mysql tables in use 1, locked 0
MySQL thread id 26208131, OS thread handle 0x7fec578e3700, query id 5274801341 10.143.90.228 root Sending data
SELECT /*!40001 SQL_NO_CACHE */ * FROM `m_flowsilver`
Trx read view will not see trx with id >= 4E0108F0, sees < 4E0108EC
---TRANSACTION 4E0108EE, ACTIVE 233 sec fetching rows
mysql tables in use 1, locked 0
MySQL thread id 26208132, OS thread handle 0x7fec7c78a700, query id 5274797797 10.143.90.228 root Sending data
SELECT /*!40001 SQL_NO_CACHE */ * FROM `m_flowmail`
Trx read view will not see trx with id >= 4E0108EF, sees < 4E0108EC

這部分內(nèi)容比較多,下面分段逐一進(jìn)行解釋:
6.1.

Trx id counter 4E0132AD #這行表示當(dāng)前事務(wù)ID,這是一個(gè)系統(tǒng)變量,每創(chuàng)建一個(gè)新事務(wù)都會增加
Purge done for trx's n:o < 4E01090B undo n:o < 0 #這是innodb清除舊MVCC行時(shí)所用的事務(wù)ID,將這個(gè)值和當(dāng)前事務(wù)ID進(jìn)行比較,就可以知道有多少老版本的數(shù)據(jù)未被清除。這個(gè)數(shù)字多大才可以安全的取值沒有硬性和速成的規(guī)定,如果數(shù)據(jù)沒做過任何更新,那么一個(gè)巨大的數(shù)字也不意味著有未清除的數(shù)據(jù),因?yàn)閷?shí)際上所有事務(wù)在數(shù)據(jù)庫里查看的都是同一個(gè)版本的數(shù)據(jù)(此時(shí)只是事務(wù)ID在增加,而數(shù)據(jù)沒有變更),另一方面,如果有很多行被更新,那每一行就會有一個(gè)或多個(gè)版本留在內(nèi)存里,減少此類開銷的最好辦法就是確保事務(wù)已完成就立即提交,不要讓它長時(shí)間地處于打開狀態(tài),因?yàn)橐粋€(gè)打開的事務(wù)即使不做任何操作,也會影響到innodb清理舊版本的行數(shù)據(jù)。 undo n:o < 0這個(gè)是innodb清理進(jìn)程正在使用的撤銷日志編號,為0 0時(shí)說明清理進(jìn)程處于空閑狀態(tài)。
History list length 1853 #歷史記錄的長度,即位于innodb數(shù)據(jù)文件的撤銷空間里的頁面的數(shù)目,如果事務(wù)執(zhí)行了更新并提交,這個(gè)數(shù)字就會增加,而當(dāng)清理進(jìn)程移除舊版本數(shù)據(jù)時(shí),它就會減少,清理進(jìn)程也會更新Purge done for.....這行中的數(shù)值。

6.2.
頭部信息之后就是一個(gè)事務(wù)列表,當(dāng)前版本的mysql還不支持嵌套事務(wù),因此,在某個(gè)時(shí)間點(diǎn)上,每個(gè)客戶端連接能夠擁有的事務(wù)數(shù)量是有一個(gè)上限的,而且每一個(gè)事務(wù)只能屬于單一連接(即一個(gè)事務(wù)只能使用單個(gè)線程執(zhí)行,不能使用多個(gè)線程)。在輸出信息里,每一個(gè)事務(wù)至少占有兩行內(nèi)容,如:

---TRANSACTION 4E0131D3, not started #每個(gè)事務(wù)的第一行以事務(wù)的ID和狀態(tài)開始,not started表示這個(gè)事務(wù)已經(jīng)提交并且沒有再發(fā)起影響事務(wù)的語句,可能剛好空閑
MySQL thread id 26208218, OS thread handle 0x7fec7c582700, query id 5274800318 10.207.162.69 gdsser#然后每個(gè)事務(wù)的第二行是一些線程等信息,MySQL thread id <數(shù)字>部分和是hi用show full processlist;命令看到的id列相同。緊隨其后的是一個(gè)內(nèi)部查詢id和一些連接信息,這些信息同樣與show full processlist中的輸出相同。
---TRANSACTION 4E01323F, not started
MySQL thread id 26208217, OS thread handle 0x7fec7c1b3700, query id 5274800938 10.207.162.69 gdsser

6.3.
上面是not started狀態(tài)的事務(wù)信息,下面來看看為ACTIVE狀態(tài)的事務(wù)信息:

---TRANSACTION 4E0110E7, ACTIVE 188 sec #這行顯示次事務(wù)處于活躍狀態(tài)已經(jīng)188s,可能的所有狀態(tài)有not started,active,prepared和committed in memory,一旦事務(wù)日志落盤了就會變成not started狀態(tài)。在時(shí)間后面會顯示出當(dāng)前事務(wù)正在做什么(在這里為空沒有顯示出來),在源代碼中有超過30個(gè)字符串常量可以顯示在時(shí)間后面,如:fetching,preparing,rows,adding foreign keys等等
mysql tables in use 1, locked 0 #該事務(wù)用到的表數(shù)和涉及表鎖的表數(shù),Innodb一般不會鎖定表,但對有些語句會鎖定,如果mysql服務(wù)器在高于innodb層之上將表鎖定,這里也是能夠顯示出來的,如果事務(wù)已經(jīng)鎖定了幾行數(shù)據(jù),這里將會有一行信息顯示出鎖定結(jié)構(gòu)的數(shù)目(注意,這跟行鎖是兩回事)和和堆大小,如:2 lock struct(s), heap size 376, 1 row lock(s), undo log entries 1,堆的大小指的是為了持有這些行鎖而占用的內(nèi)存大小,Innodb是用一種特殊的位圖表來實(shí)現(xiàn)行鎖的,從理論上講,它可將每一個(gè)鎖定的行表示為一個(gè)比特,經(jīng)測試顯示,每個(gè)鎖通常不超過4比特。
MySQL thread id 26208154, OS thread handle 0x7fec7c235700, query id 5274800671 10.143.90.228 root Sending data #與show processlist輸出結(jié)果大部分相同
SELECT /*!40001 SQL_NO_CACHE */ * FROM `m_flowskillpoint` #如果事務(wù)正在運(yùn)行一個(gè)查詢,那么這里就會顯示事務(wù)涉及的SQL,注意:有些版本可能只顯示其中一小段,而不是完整的SQL
Trx read view will not see trx with id >= 4E0110E8, sees < 4E0108EE #這行顯示了事務(wù)的讀視圖,它表明了因?yàn)榘姹娟P(guān)系而產(chǎn)生的對于事務(wù)可見和不可見兩種類型的事務(wù)ID的范圍,在這里,兩個(gè)數(shù)字之間有一個(gè)事務(wù)的間隙,這個(gè)間隙里的事務(wù)可能是不可見的,innodb在執(zhí)行查詢時(shí),對于那些事務(wù)ID正好在這個(gè)間隙的行,還會檢查其可見性。

注:如果事務(wù)正在等待一個(gè)鎖,那么在查詢SQL文本后面將可以看到這個(gè)鎖的信息,在上文的死鎖例子里,這樣的信息看到過很多了,不幸的是,輸出信息并沒有說出這個(gè)鎖正被其他哪個(gè)事務(wù)持有,不過可以通過information_schema庫下的innodb_trx,innodb_lock_waits,innodb_locks三個(gè)表來查明這一點(diǎn)。如果輸出信息里有很多個(gè)事務(wù),innodb可能會限制要打印出來的事務(wù)數(shù)目,以免輸出信息增長得太大,這時(shí)就會看到...truncated...提示。


7.FILE I/O部分顯示的是I/O輔助線程的狀態(tài),還有性能計(jì)數(shù)器的狀態(tài),如下:

--------
FILE I/O
--------
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: doing file i/o (read thread) ev set #以上為默認(rèn)的4個(gè)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) #以上為默認(rèn)的4個(gè)write thread
Pending normal aio reads: 128 [0, 0, 0, 128] , aio writes: 0 [0, 0, 0, 0] , #讀線程和寫線程掛起操作的數(shù)目等,aio的意思是異步I/O
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0 #insert buffer thread掛起的fsync()操作數(shù)目等
Pending flushes (fsync) log: 0; buffer pool: 0 #log thread掛起的fsync()操作數(shù)目等
146246831 OS file reads, 760501349 OS file writes, 247143684 OS fsyncs #這行顯示了讀,寫和fsync()調(diào)用執(zhí)行的數(shù)目,在你的機(jī)器環(huán)境負(fù)載下這些絕對值可能會有所不同,因此更重要的是監(jiān)控它們過去一段時(shí)間內(nèi)是如何改變的。
1 pending preads, 0 pending pwrites #這行顯示了當(dāng)前被掛起的讀和寫操作數(shù)
145.49 reads/s, 783677 avg bytes/read, 28.75 writes/s, 10.67 fsyncs/s #這行顯示了在頭部顯示的時(shí)間(指的是第1部分的時(shí)間)段內(nèi)的每秒平均值。

注:三行掛起讀寫線程、緩沖池線程、日志線程的統(tǒng)計(jì)信息的值是檢測I/O受限的應(yīng)用的一個(gè)好方法,如果這些I/O大部分有掛起操作,那么負(fù)載可能I/O受限。在linux系統(tǒng)下使用參數(shù):innodb_read_io_threads和innodb_write_io_threads兩個(gè)變量來配置讀寫線程的數(shù)量,默認(rèn)為各4個(gè)線程。
insert buffer thread:負(fù)責(zé)插入緩沖合并,如:記錄被從插入緩沖合并到表空間中
log thread:負(fù)責(zé)異步刷事務(wù)日志
read thread:執(zhí)行預(yù)讀操作以嘗試預(yù)先讀取innodb預(yù)感需要的數(shù)據(jù)
write thread:刷新臟頁緩沖


8.這部分顯示了insert buffer和adaptive hash index兩個(gè)部分的結(jié)構(gòu)的狀態(tài)

-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------


Ibuf: size 12, free list len 27559, seg size 27572, 18074934 merges #這行顯示了關(guān)于size(size 12代表了已經(jīng)合并記錄頁的數(shù)量)、free list(代表了插入緩沖中空閑列表長度)和seg size大?。╯eg size 27572顯示了當(dāng)前insert buffer的長度,大小為27572*16K=440M左右)的信息。18074934 merges代表合并插入的次數(shù)
merged operations: #這個(gè)標(biāo)簽下的一行信息insert,delete mark,delete分別表示merge操作合并了多少個(gè)insert buffer,delete buffer,purge buffer
insert 81340470, delete mark 8893610, delete 818579

discarded operations: #這個(gè)標(biāo)簽下的一行信息表示當(dāng)change buffer發(fā)生merge時(shí)表已經(jīng)被刪除了,就不需要再將記錄合并到輔助索引中了
insert 0, delete mark 0, delete 0
Hash table size 87709057, node heap has 10228 buffer(s) #這行顯示了自使用哈希索引的狀態(tài),其中,Hash table size 87709057表示AHI的大小,node heap has 10228 buffer(s)表示AHI的使用情況
1741.05 hash searches/s, 539.48 non-hash searches/s #這行顯示了在頭部第1部分提及的時(shí)間內(nèi)Innodb每秒完成了多少哈希索引操作,1741.05 hash searches/s表示每秒使用AHI搜索的情況,539.48 non-hash searches/s表示每秒沒有使用AHI搜索的情況(因?yàn)楣K饕荒苡糜诘戎挡樵?,而范圍查詢,模糊查詢是不能使用哈希索引的?,通過hash searches: non-hash searches的比例大概可以了解使用哈希索引后的效率,哈希索引查找與非哈希索引查找的比例僅供參考,自適應(yīng)哈希索引無法配置,但是可以通過innodb_adaptive_hash_index=ON|OFF參數(shù)來選擇是否需要這個(gè)特性。

注:


innodb從1.0.x開始引入change buffer,可以視為insert buffer的升級,從這個(gè)版本開始,innodb可以對DML操作(insert,delete,update)都進(jìn)行緩沖,他們分別是insert buffer,delete buffer,purge buffer,當(dāng)然和之前insert buffer一樣,change buffer適用對象仍然是非唯一索引的輔助索引,因?yàn)闆]有update buffer,所以對一條記錄進(jìn)行update的操作可以分為兩個(gè)過程:

A:將記錄標(biāo)記為刪除

B:真正將記錄刪除

因此,delete buffer對應(yīng)update 操作的第一個(gè)過程,即將記錄標(biāo)記為刪除,purge buffer對應(yīng)update的第二個(gè)過程,即將記錄真正地刪除




9.這部分顯示了關(guān)于innodb事務(wù)日志(重做日志)子系統(tǒng)的統(tǒng)計(jì):

---
LOG
---
Log sequence number 1351392990515 #這行顯示了當(dāng)前最新數(shù)據(jù)產(chǎn)生的日志序列號
Log flushed up to 1351392989504 #這行顯示了日志已經(jīng)刷新到哪個(gè)位置了(已經(jīng)落盤到事務(wù)日志中的日志序列號)
Last checkpoint at 1351373900020 #這行顯示了上一次檢查點(diǎn)的位置(一個(gè)檢查點(diǎn)表示一個(gè)數(shù)據(jù)和日志文件都處于一致狀態(tài)的時(shí)刻,并且能用于恢復(fù)數(shù)據(jù)),如果上一次檢查點(diǎn)落后與上一行太多,并且差異接近于事務(wù)日志文件的大小,Innodb會觸發(fā)“瘋狂刷”,這對性能而言非常糟糕。
0 pending log writes, 0 pending chkp writes #這行顯示了當(dāng)前掛起的日志讀寫操作,可以將這行的值與第7部分FILE I/O對應(yīng)的值做比較,以了解你的I/O有多少是由于日志系統(tǒng)引起的。
286879989 log i/o's done, 15.92 log i/o's/second #這行顯示了日志操作的統(tǒng)計(jì)和每秒日志I/O數(shù),可以將這行的值與第7部分FILE I/O對應(yīng)的值做比較,以了解你的I/O有多少是由于日志系統(tǒng)引起的。


9.這部分顯示了關(guān)于innodb緩沖池及其如何使用內(nèi)存的統(tǒng)計(jì):
9.1.

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 45357793280; in additional pool allocated 0 #這行顯示了由innodb分配的總內(nèi)存,以及其中多少是額外內(nèi)存池分配,額外內(nèi)存池僅分配了其中很小一部分內(nèi)存,由內(nèi)部內(nèi)存分配器分配,現(xiàn)在的innodb版本一般使用操作系統(tǒng)的內(nèi)存分配器,但老版本使用自己的,這是由于在那個(gè)時(shí)代有些操作系統(tǒng)并未提供一個(gè)非常好的內(nèi)存分配實(shí)現(xiàn)。
Dictionary memory allocated 12681573


Buffer pool size 2705015 #從這行開始的下面4行顯示緩沖池度量值,以頁為單位,度量值有總的緩沖池大小,空閑頁數(shù),分配用來存儲數(shù)據(jù)庫頁的頁數(shù),以及臟數(shù)據(jù)庫頁數(shù)。這行顯示了緩沖池總共有多少個(gè)頁,即即2705015*16K,共有43G的緩沖池
Free buffers 5 #這行顯示了緩沖池空閑頁數(shù)
Database pages 2694782 #這行顯示了分配用來存儲數(shù)據(jù)庫頁的頁數(shù),即,表示LRU列表中頁的數(shù)量,包含young sublist和old sublist
Old database pages 994651 #這行顯示了LRU中的old sublist部分頁的數(shù)量
Modified db pages 10610 #這行顯示臟數(shù)據(jù)庫頁數(shù)
Pending reads 128 #這行顯示了掛起讀的數(shù)量
Pending writes: LRU 0, flush list 0, single page 0 #這行顯示了掛起寫的數(shù)量
#注意,這里掛起的讀和寫操作并不與FILE I/O部分的值匹配,因?yàn)镮nnodb可能合并許多的邏輯讀寫操作到一個(gè)物理I/O操作中,LRU代表最近使用到的被掛起數(shù)量,它是通過沖刷緩沖中不經(jīng)常使用的頁來釋放空間以供給經(jīng)常使用的頁的一種方法,沖刷列表flush list存放著檢查點(diǎn)處理需要沖刷的舊頁被掛起的數(shù)量,單頁single page被掛起的數(shù)量(single page寫是獨(dú)立的頁面寫,不會被合并)。
Pages made young 3014373561, not young 0 #這行顯示了LRU列表中頁移動到LRU首部的次數(shù),因?yàn)樵摲?wù)器在運(yùn)行階段改變沒有達(dá)到innodb_old_blocks_time閥值的值,因此not young為0
6960.42 youngs/s, 0.00 non-youngs/s #表示每秒young和non-youngs這兩類操作的次數(shù)


Pages read 2946570833, created 43450158, written 574214278 #這行顯示了innodb被讀取,創(chuàng)建,寫入了多少頁,讀/寫頁的值是指的從磁盤讀到緩沖池的數(shù)據(jù),或者從緩沖池寫到磁盤中的數(shù)據(jù),創(chuàng)建頁指的是innodb在緩沖池中分配但沒有從數(shù)據(jù)文件中讀取內(nèi)容的頁,因?yàn)樗⒉魂P(guān)心內(nèi)容是什么(如,它們可能屬于一個(gè)已經(jīng)被刪除的表)
6960.54 reads/s, 4.42 creates/s, 9.33 writes/s #這行顯示了對應(yīng)上面一行的每秒read,create,write的頁數(shù)
Buffer pool hit rate 955 / 1000, young-making rate 45 / 1000 not 0 / 1000 #這行顯示了緩沖池的命中率,它用來衡量innodb在緩沖池中查找到所需頁的比例,它度量自上次Innodb狀態(tài)輸出后到本次輸出這段時(shí)間內(nèi)的命中率,因此,如果服務(wù)器自那以后一直很安靜,你將會看到No buffer pool page gets since the last printout。它對于度量緩存池的大小并沒有用處。


Pages read ahead 6928.54/s, evicted without access 8.21/s, Random read ahead 0.00/s #這行顯示了頁面預(yù)讀,隨機(jī)預(yù)讀的每秒頁數(shù)
LRU len: 2694782, unzip_LRU len: 0 #innodb1.0.x開始支持壓縮頁的功能,將原來16K的頁壓縮為1K,2K,4K,8K,而由于頁的大小發(fā)生了變化,LRU列表也有了些改變,對于非16K的頁,是通過unzip_LRU列表進(jìn)行管理的,可以看到unzip_LRU len為0表示沒有使用壓縮頁.
I/O sum[60790]:cur[30], unzip sum[0]:cur[0]



對于壓縮頁的表,每個(gè)表的壓縮比例可能不同,可能存在有的表頁大小為8K,有的表頁大小為2K的情況,unzip_LRUs 怎樣從緩存池中分配內(nèi)存的呢?

首先,在unzip_LRU列表中對不同壓縮頁大小的頁進(jìn)行分別管理,其次,通過伙伴算法進(jìn)行內(nèi)存的分配,例如:需要從緩存池中申請頁為4K的大小,其過程如下:

a:檢查4K的unzip_LRU列表,檢查是否有可用的空閑頁

b:若有,則直接使用

c:若沒有,檢查8K的unzip_LRU列表

d:若能夠得到空閑頁,將頁分成2個(gè)4K的頁,存放到4K的unzip_LRU列表

e:若不能得到空閑頁,從LRU列表中申請一個(gè)16K的頁,將頁分成1個(gè)8K,2個(gè)4K的頁,分別存放到各自大小對應(yīng)的unzip_LRU列表中。



注:可能出現(xiàn)Free buffers和Database pages之和不等于Buffer pool size,因?yàn)榫彌_池中的頁肯會被分配給自適應(yīng)哈希索引,lock信息,insert buffer等,而這部分頁不需要LRU算法進(jìn)行維護(hù),因此不在LRU列表中。





9.2.如果innodb buffer pool使用參數(shù)innodb

_buffer_pool_instances=num設(shè)置了大于1個(gè)緩沖池實(shí)例,那么就會按照這個(gè)參數(shù)把innodb_buffer_pool_size=xxx平分為num份。每份的信息顯示類似如下,這部分的內(nèi)容和9.1小節(jié)內(nèi)容類似,就不再多說。

----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size 541003
Free buffers 1
Database pages 538965
Old database pages 198933
Modified db pages 2190
Pending reads 128
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 603372180, not young 0
1441.81 youngs/s, 0.00 non-youngs/s
Pages read 589705199, created 8703138, written 116954697
1441.61 reads/s, 0.75 creates/s, 1.83 writes/s
Buffer pool hit rate 955 / 1000, young-making rate 45 / 1000 not 0 / 1000
Pages read ahead 1436.98/s, evicted without access 0.87/s, Random read ahead 0.00/s
LRU len: 538965, unzip_LRU len: 0
I/O sum[12158]:cur[6], unzip sum[0]:cur[0]
---BUFFER POOL 1
Buffer pool size 541003
Free buffers 1
Database pages 538959
Old database pages 198931
Modified db pages 2025
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 602366394, not young 0
1481.35 youngs/s, 0.00 non-youngs/s
Pages read 588738997, created 8708171, written 113209540
1480.56 reads/s, 0.83 creates/s, 1.92 writes/s
Buffer pool hit rate 958 / 1000, young-making rate 42 / 1000 not 0 / 1000
Pages read ahead 1473.73/s, evicted without access 1.96/s, Random read ahead 0.00/s
LRU len: 538959, unzip_LRU len: 0
I/O sum[12158]:cur[6], unzip sum[0]:cur[0]



10.這部分顯示了其他各項(xiàng)的innodb統(tǒng)計(jì):

--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue #這行顯示了innodb內(nèi)核內(nèi)有多少個(gè)線程,隊(duì)列中有多少個(gè)線程,隊(duì)列中的查詢是innodb為限制并發(fā)執(zhí)行的線程數(shù)量而不運(yùn)行進(jìn)入內(nèi)核的線程。查詢在進(jìn)入隊(duì)列之前會休眠等待。
5 read views open inside InnoDB #這行顯示了有多少打開的innodb讀視圖,讀視圖是包含事務(wù)開始點(diǎn)的數(shù)據(jù)庫內(nèi)容的MVCC快照,你可以看看某特定事務(wù)在第6部分TRANSACTIONS是否有讀視圖
Main thread process no. 4368, id 140653691242240, state: sleeping #這行顯示了內(nèi)核的主線程狀態(tài)
Number of rows inserted 3429012215, updated 153529675, deleted 112310240, read 3739562987410 #這行顯示了多少行被插入,更新和刪除,讀取
428.52 inserts/s, 7.21 updates/s, 0.46 deletes/s, 1047933.92 reads/s #這行顯示了對應(yīng)上面一行的每秒平均值,如果想查看innodb有多少工作量在進(jìn)行,那么這兩行是很好的參考值
----------------------------
END OF INNODB MONITOR OUTPUT #要注意了,如果看不到這行輸出,可能是有大量事務(wù)或者是有一個(gè)大的死鎖截?cái)嗔溯敵鲂畔?/strong>
============================

注:內(nèi)核的主線程狀態(tài)可能的狀態(tài)值有如下一些:

A:doing background drop tables

B:doing insert buffer merge

C:flushing buffer pool pages

D:making checkpoint

E:purging

F:reserving kernel mutex

G:sleeping

H:suspending

I:waiting for buffer pool flush to end

J:waiting for server activity
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI