數據庫對象事件與屬性統計 | performance_schema全方位介紹

上一篇 《事件統計 | performance_schema全方位介紹》 詳細介紹了performance_schema的事件統計表,但這些統計數據粒度太粗,僅僅按照事件的5大類別+用戶、線程等維度進行分類統計,但有時候我們需要從更細粒度的維度進行分類統計,例如:某個表的IO開銷多少、鎖開銷多少、以及用戶連接的一些屬性統計信息等。此時就需要查看數據庫對象事件統計表與屬性統計表了。今天將帶領大家一起踏上系列第五篇的征程(全系共7個篇章),本期將爲大家全面講解performance_schema中對象事件統計表與屬性統計表。下面,請跟隨我們一起開始performance_schema系統的學習之旅吧~

友情提示:下文中的統計表中大部分字段含義與上一篇 《事件統計 | performance_schema全方位介紹》 中提到的統計表字段含義相同,下文中不再贅述。此外,由於部分統計表中的記錄內容過長,限於篇幅會省略部分文本,如有需要請自行安裝MySQL 5.7.11以上版本跟隨本文進行同步操作查看。

01

數據庫對象統計表

1.數據庫表級別對象等待事件統計

按照數據庫對象名稱(庫級別對象和表級別對象,如:庫名和表名)進行統計的等待事件。按照OBJECT_TYPE、OBJECT_SCHEMA、OBJECT_NAME列進行分組,按照COUNT_STAR、xxx_TIMER_WAIT字段進行統計。包含一張objects_summary_global_by_type表。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 11:10:42> select * from objects_summary_global_by_type where SUM_TIMER_WAIT!=0\G;
*************************** 1. row ***************************
OBJECT_TYPE: TABLE
OBJECT_SCHEMA: xiaoboluo
OBJECT_NAME: test
COUNT_STAR: 56
SUM_TIMER_WAIT: 195829830101250
MIN_TIMER_WAIT: 2971125
AVG_TIMER_WAIT: 3496961251500
MAX_TIMER_WAIT: 121025235946125
1 row in set (0.00 sec)

從表中的記錄內容可以看到,按照庫xiaoboluo下的表test進行分組,統計了表相關的等待事件調用次數,總計、最小、平均、最大延遲時間信息,利用這些信息,我們可以大致瞭解InnoDB中表的訪問效率排行統計情況,一定程度上反應了對存儲引擎接口調用的效率。

2.表I/O等待和鎖等待事件統計

與objects_summary_global_by_type 表統計信息類似,表I/O等待和鎖等待事件統計信息更爲精細,細分了每個表的增刪改查的執行次數,總等待時間,最小、最大、平均等待時間,甚至精細到某個索引的增刪改查的等待時間,表IO等待和鎖等待事件instruments(wait/io/table/sql/handler和wait/lock/table/sql/handler )默認開啓,在setup_consumers表中無具體的對應配置,默認表IO等待和鎖等待事件統計表中就會統計相關事件信息。包含如下幾張表:

admin@localhost : performance_schema 06:50:03> show tables like '%table%summary%';
+------------------------------------------------+
| Tables_in_performance_schema (%table%summary%) |
+------------------------------------------------+
| table_io_waits_summary_by_index_usage | # 按照每個索引進行統計的表I/O等待事件
| table_io_waits_summary_by_table | # 按照每個表進行統計的表I/O等待事件
| table_lock_waits_summary_by_table | # 按照每個表進行統計的表鎖等待事件
+------------------------------------------------+
3 rows in set (0.00 sec)

我們先來看看錶中記錄的統計信息是什麼樣子的。

# table_io_waits_summary_by_index_usage表
admin@localhost : performance_schema 01:55:49> select * from table_io_waits_summary_by_index_usage where SUM_TIMER_WAIT!=0\G;
*************************** 1. row ***************************
OBJECT_TYPE: TABLE
OBJECT_SCHEMA: xiaoboluo
OBJECT_NAME: test
  INDEX_NAME: PRIMARY
  COUNT_STAR: 1
SUM_TIMER_WAIT: 56688392
MIN_TIMER_WAIT: 56688392
AVG_TIMER_WAIT: 56688392
MAX_TIMER_WAIT: 56688392
  COUNT_READ: 1
SUM_TIMER_READ: 56688392
MIN_TIMER_READ: 56688392
AVG_TIMER_READ: 56688392
MAX_TIMER_READ: 56688392
......
1 row in set (0.00 sec)
# table_io_waits_summary_by_table表
admin@localhost : performance_schema 01:56:16> select * from table_io_waits_summary_by_table where SUM_TIMER_WAIT!=0\G;
*************************** 1. row ***************************
OBJECT_TYPE: TABLE
OBJECT_SCHEMA: xiaoboluo
OBJECT_NAME: test
  COUNT_STAR: 1
............
1 row in set (0.00 sec)
# table_lock_waits_summary_by_table表
admin@localhost : performance_schema 01:57:20> select * from table_lock_waits_summary_by_table where SUM_TIMER_WAIT!=0\G;
*************************** 1. row ***************************
                  OBJECT_TYPE: TABLE
                OBJECT_SCHEMA: xiaoboluo
                  OBJECT_NAME: test
............
            COUNT_READ_NORMAL: 0
        SUM_TIMER_READ_NORMAL: 0
        MIN_TIMER_READ_NORMAL: 0
        AVG_TIMER_READ_NORMAL: 0
        MAX_TIMER_READ_NORMAL: 0
COUNT_READ_WITH_SHARED_LOCKS: 0
SUM_TIMER_READ_WITH_SHARED_LOCKS: 0
MIN_TIMER_READ_WITH_SHARED_LOCKS: 0
AVG_TIMER_READ_WITH_SHARED_LOCKS: 0
MAX_TIMER_READ_WITH_SHARED_LOCKS: 0
......
1 row in set (0.00 sec)

從上面表中的記錄信息我們可以看到,table_io_waits_summary_by_index_usage表和table_io_waits_summary_by_table有着類似的統計列,但table_io_waits_summary_by_table表是包含整個表的增刪改查等待事件分類統計,table_io_waits_summary_by_index_usage區分了每個表的索引的增刪改查等待事件分類統計,而table_lock_waits_summary_by_table表統計緯度類似,但它是用於統計增刪改查對應的鎖等待時間,而不是IO等待時間,這些表的分組和統計列含義請大家自行舉一反三,這裏不再贅述,下面針對這三張表做一些必要的說明:

table_io_waits_summary_by_table表:

該表允許使用TRUNCATE TABLE語句。只將統計列重置爲零,而不是刪除行。對該表執行truncate還會隱式truncate table_io_waits_summary_by_index_usage表

table_io_waits_summary_by_index_usage表:

按照與table_io_waits_summary_by_table的分組列+INDEX_NAME列進行分組,INDEX_NAME有如下幾種 : 

· 如果使用到了索引,則這裏顯示索引的名字,如果爲PRIMARY,則表示表I/O使用到了主鍵索引 

· 如果值爲NULL,則表示表I/O沒有使用到索引 

· 如果是插入操作,則無法使用到索引,此時的統計值是按照INDEX_NAME = NULL計算的

該表允許使用TRUNCATE TABLE語句。只將統計列重置爲零,而不是刪除行。該表執行truncate時也會隱式觸發table_io_waits_summary_by_table表的truncate操作。另外使用DDL語句更改索引結構時,會導致該表的所有索引統計信息被重置

table_lock_waits_summary_by_table表:

該表的分組列與table_io_waits_summary_by_table表相同

該表包含有關內部和外部鎖的信息: 

· 內部鎖對應SQL層中的鎖。是通過調用thr_lock()函數來實現的。(官方手冊上說有一個OPERATION列來區分鎖類型,該列有效值爲:read normal、read with shared locks、read high priority、read no insert、write allow write、write concurrent insert、write delayed、write low priority、write normal。但在該表的定義上並沒有看到該字段) 

· 外部鎖對應存儲引擎層中的鎖。通過調用handler::external_lock()函數來實現。(官方手冊上說有一個OPERATION列來區分鎖類型,該列有效值爲:read external、write external。但在該表的定義上並沒有看到該字段)

該表允許使用TRUNCATE TABLE語句。只將統計列重置爲零,而不是刪除行。

3.文件I/O事件統計

文件I/O事件統計表只記錄等待事件中的IO事件(不包含table和socket子類別),文件I/O事件instruments默認開啓,在setup_consumers表中無具體的對應配置。它包含如下兩張表:

admin@localhost : performance_schema 06:48:12> show tables like '%file_summary%';
+-----------------------------------------------+
| Tables_in_performance_schema (%file_summary%) |
+-----------------------------------------------+
| file_summary_by_event_name                    |
| file_summary_by_instance                      |
+-----------------------------------------------+
2 rows in set (0.00 sec)

兩張表中記錄的內容很相近:

· file_summary_by_event_name:按照每個事件名稱進行統計的文件IO等待事件

· file_summary_by_instance:按照每個文件實例(對應具體的每個磁盤文件,例如:表sbtest1的表空間文件sbtest1.ibd)進行統計的文件IO等待事件

我們先來看看錶中記錄的統計信息是什麼樣子的。

# file_summary_by_event_name表
admin@localhost : performance_schema 11:00:44> select * from file_summary_by_event_name where SUM_TIMER_WAIT !=0 and EVENT_NAME like '%innodb%' limit 1\G;
*************************** 1. row ***************************
          EVENT_NAME: wait/io/file/innodb/innodb_data_file
          COUNT_STAR: 802
      SUM_TIMER_WAIT: 412754363625
      MIN_TIMER_WAIT: 0
      AVG_TIMER_WAIT: 514656000
      MAX_TIMER_WAIT: 9498247500
          COUNT_READ: 577
      SUM_TIMER_READ: 305970952875
      MIN_TIMER_READ: 15213375
      AVG_TIMER_READ: 530278875
      MAX_TIMER_READ: 9498247500
SUM_NUMBER_OF_BYTES_READ: 11567104
......
1 row in set (0.00 sec)
# file_summary_by_instance表
admin@localhost : performance_schema 11:01:23> select * from file_summary_by_instance where SUM_TIMER_WAIT!=0 and EVENT_NAME like '%innodb%' limit 1\G;
*************************** 1. row ***************************
            FILE_NAME: /data/mysqldata1/innodb_ts/ibdata1
          EVENT_NAME: wait/io/file/innodb/innodb_data_file
OBJECT_INSTANCE_BEGIN: 139882156936704
          COUNT_STAR: 33
............
1 row in set (0.00 sec)

從上面表中的記錄信息我們可以看到:

· 每個文件I/O統計表都有一個或多個分組列,以表明如何統計這些事件信息。這些表中的事件名稱來自setup_instruments表中的name字段: 

* file_summary_by_event_name表:按照EVENT_NAME列進行分組 ;

* file_summary_by_instance表:有額外的FILE_NAME、OBJECT_INSTANCE_BEGIN列,按照FILE_NAME、EVENT_NAME列進行分組,與file_summary_by_event_name 表相比,file_summary_by_instance表多了FILE_NAME和OBJECT_INSTANCE_BEGIN字段,用於記錄具體的磁盤文件相關信息。

· 每個文件I/O事件統計表有如下統計字段:

* COUNT_STAR,SUM_TIMER_WAIT,MIN_TIMER_WAIT,AVG_TIMER_WAIT,MAX_TIMER_WAIT:這些列統計所有I/O操作數量和操作時間 ;

* COUNT_READ,SUM_TIMER_READ,MIN_TIMER_READ,AVG_TIMER_READ,MAX_TIMER_READ,SUM_NUMBER_OF_BYTES_READ:這些列統計了所有文件讀取操作,包括FGETS,FGETC,FREAD和READ系統調用,還包含了這些I/O操作的數據字節數 ;

* COUNT_WRITE,SUM_TIMER_WRITE,MIN_TIMER_WRITE,AVG_TIMER_WRITE,MAX_TIMER_WRITE,SUM_NUMBER_OF_BYTES_WRITE:這些列統計了所有文件寫操作,包括FPUTS,FPUTC,FPRINTF,VFPRINTF,FWRITE和PWRITE系統調用,還包含了這些I/O操作的數據字節數 ;

* COUNT_MISC,SUM_TIMER_MISC,MIN_TIMER_MISC,AVG_TIMER_MISC,MAX_TIMER_MISC:這些列統計了所有其他文件I/O操作,包括CREATE,DELETE,OPEN,CLOSE,STREAM_OPEN,STREAM_CLOSE,SEEK,TELL,FLUSH,STAT,FSTAT,CHSIZE,RENAME和SYNC系統調用。注意:這些文件I/O操作沒有字節計數信息。

文件I/O事件統計表允許使用TRUNCATE TABLE語句。但只將統計列重置爲零,而不是刪除行。

PS:MySQL server使用幾種緩存技術通過緩存從文件中讀取的信息來避免文件I/O操作。當然,如果內存不夠時或者內存競爭比較大時可能導致查詢效率低下,這個時候您可能需要通過刷新緩存或者重啓server來讓其數據通過文件I/O返回而不是通過緩存返回。

4.套接字事件統計

套接字事件統計了套接字的讀寫調用次數和發送接收字節計數信息,socket事件instruments默認關閉,在setup_consumers表中無具體的對應配置,包含如下兩張表:

· socket_summary_by_instance:針對每個socket實例的所有 socket I/O操作,這些socket操作相關的操作次數、時間和發送接收字節信息由wait/io/socket/* instruments產生。但當連接中斷時,在該表中對應socket連接的信息行將被刪除(這裏的socket是指的當前活躍的連接創建的socket實例)

· socket_summary_by_event_name:針對每個socket I/O instruments,這些socket操作相關的操作次數、時間和發送接收字節信息由wait/io/socket/* instruments產生(這裏的socket是指的當前活躍的連接創建的socket實例)

可通過如下語句查看:

admin@localhost : performance_schema 06:53:42> show tables like '%socket%summary%';
+-------------------------------------------------+
| Tables_in_performance_schema (%socket%summary%) |
+-------------------------------------------------+
| socket_summary_by_event_name                    |
| socket_summary_by_instance                      |
+-------------------------------------------------+
2 rows in set (0.00 sec)

我們先來看看錶中記錄的統計信息是什麼樣子的。

# socket_summary_by_event_name表
root@localhost : performance_schema 04:44:00> select * from socket_summary_by_event_name\G;
*************************** 1. row ***************************
           EVENT_NAME: wait/io/socket/sql/server_tcpip_socket
           COUNT_STAR: 2560
       SUM_TIMER_WAIT: 62379854922
       MIN_TIMER_WAIT: 1905016
       AVG_TIMER_WAIT: 24366870
       MAX_TIMER_WAIT: 18446696808701862260
           COUNT_READ: 0
       SUM_TIMER_READ: 0
       MIN_TIMER_READ: 0
       AVG_TIMER_READ: 0
       MAX_TIMER_READ: 0
SUM_NUMBER_OF_BYTES_READ: 0
......
*************************** 2. row ***************************
           EVENT_NAME: wait/io/socket/sql/server_unix_socket
           COUNT_STAR: 24
......
*************************** 3. row ***************************
           EVENT_NAME: wait/io/socket/sql/client_connection
           COUNT_STAR: 213055844
......
3 rows in set (0.00 sec)
# socket_summary_by_instance表
root@localhost : performance_schema 05:11:45> select * from socket_summary_by_instance where COUNT_STAR!=0\G;
*************************** 1. row ***************************
           EVENT_NAME: wait/io/socket/sql/server_tcpip_socket
OBJECT_INSTANCE_BEGIN: 2655350784
......
*************************** 2. row ***************************
           EVENT_NAME: wait/io/socket/sql/server_unix_socket
OBJECT_INSTANCE_BEGIN: 2655351104
......
*************************** 3. row ***************************
           EVENT_NAME: wait/io/socket/sql/client_connection
OBJECT_INSTANCE_BEGIN: 2658003840
......
*************************** 4. row ***************************
           EVENT_NAME: wait/io/socket/sql/client_connection
OBJECT_INSTANCE_BEGIN: 2658004160
......
4 rows in set (0.00 sec)

從上面表中的記錄信息我們可以看到(與文件I/O事件統計類似,兩張表也分別按照socket事件類型統計與按照socket instance進行統計)

· socket_summary_by_event_name表:按照EVENT_NAME列進行分組

· socket_summary_by_instance表:按照EVENT_NAME(該列有效值爲wait/io/socket/sql/client_connection、wait/io/socket/sql/server_tcpip_socket、wait/io/socket/sql/server_unix_socket:)、OBJECT_INSTANCE_BEGIN列進行分組

每個套接字統計表都包含如下統計列:

· COUNT_STAR,SUM_TIMER_WAIT,MIN_TIMER_WAIT,AVG_TIMER_WAIT,MAX_TIMER_WAIT:這些列統計所有socket讀寫操作的次數和時間信息

· COUNT_READ,SUM_TIMER_READ,MIN_TIMER_READ,AVG_TIMER_READ,MAX_TIMER_READ,SUM_NUMBER_OF_BYTES_READ:這些列統計所有接收操作(socket的RECV、RECVFROM、RECVMS類型操作,即以server爲參照的socket讀取數據的操作)相關的次數、時間、接收字節數等信息

· COUNT_WRITE,SUM_TIMER_WRITE,MIN_TIMER_WRITE,AVG_TIMER_WRITE,MAX_TIMER_WRITE,SUM_NUMBER_OF_BYTES_WRITE:這些列統計了所有發送操作(socket的SEND、SENDTO、SENDMSG類型操作,即以server爲參照的socket寫入數據的操作)相關的次數、時間、接收字節數等信息

· COUNT_MISC,SUM_TIMER_MISC,MIN_TIMER_MISC,AVG_TIMER_MISC,MAX_TIMER_MISC:這些列統計了所有其他套接字操作,如socket的CONNECT、LISTEN,ACCEPT、CLOSE、SHUTDOWN類型操作。注意:這些操作沒有字節計數

套接字統計表允許使用TRUNCATE TABLE語句(除events_statements_summary_by_digest之外),只將統計列重置爲零,而不是刪除行。

PS:socket統計表不會統計空閒事件生成的等待事件信息,空閒事件的等待信息是記錄在等待事件統計表中進行統計的。

5.prepare語句實例統計表

performance_schema提供了針對prepare語句的監控記錄,並按照如下方法對錶中的內容進行管理。

· prepare語句預編譯:COM_STMT_PREPARE或SQLCOM_PREPARE命令在server中創建一個prepare語句。如果語句檢測成功,則會在prepared_statements_instances表中新添加一行。如果prepare語句無法檢測,則會增加Performance_schema_prepared_statements_lost狀態變量的值。

· prepare語句執行:爲已檢測的prepare語句實例執行COM_STMT_EXECUTE或SQLCOM_PREPARE命令,同時會更新prepare_statements_instances表中對應的行信息。

· prepare語句解除資源分配:對已檢測的prepare語句實例執行COM_STMT_CLOSE或SQLCOM_DEALLOCATE_PREPARE命令,同時將刪除prepare_statements_instances表中對應的行信息。爲了避免資源泄漏,請務必在prepare語句不需要使用的時候執行此步驟釋放資源。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 10:50:38> select * from prepared_statements_instances\G;
*************************** 1. row ***************************
  OBJECT_INSTANCE_BEGIN: 139968890586816
          STATEMENT_ID: 1
        STATEMENT_NAME: stmt
              SQL_TEXT: SELECT 1
        OWNER_THREAD_ID: 48
        OWNER_EVENT_ID: 54
      OWNER_OBJECT_TYPE: NULL
    OWNER_OBJECT_SCHEMA: NULL
      OWNER_OBJECT_NAME: NULL
          TIMER_PREPARE: 896167000
        COUNT_REPREPARE: 0
          COUNT_EXECUTE: 0
      SUM_TIMER_EXECUTE: 0
      MIN_TIMER_EXECUTE: 0
      AVG_TIMER_EXECUTE: 0
      MAX_TIMER_EXECUTE: 0
          SUM_LOCK_TIME: 0
            SUM_ERRORS: 0
          SUM_WARNINGS: 0
      SUM_ROWS_AFFECTED: 0
          SUM_ROWS_SENT: 0
......
1 row in set (0.00 sec)

prepared_statements_instances表字段含義如下:

· OBJECT_INSTANCE_BEGIN:prepare語句事件的instruments 實例內存地址。

· STATEMENT_ID:由server分配的語句內部ID。文本和二進制協議都使用該語句ID。

· STATEMENT_NAME:對於二進制協議的語句事件,此列值爲NULL。對於文本協議的語句事件,此列值是用戶分配的外部語句名稱。例如:PREPARE stmt FROM'SELECT 1';,語句名稱爲stmt。

· SQL_TEXT:prepare的語句文本,帶“?”的表示是佔位符標記,後續execute語句可以對該標記進行傳參。

· OWNER_THREAD_ID,OWNER_EVENT_ID:這些列表示創建prepare語句的線程ID和事件ID。

· OWNER_OBJECT_TYPE,OWNER_OBJECT_SCHEMA,OWNER_OBJECT_NAME:對於由客戶端會話使用SQL語句直接創建的prepare語句,這些列值爲NULL。對於由存儲程序創建的prepare語句,這些列值顯示相關存儲程序的信息。如果用戶在存儲程序中忘記釋放prepare語句,那麼這些列可用於查找這些未釋放的prepare對應的存儲程序,使用語句查詢:SELECT OWNER_OBJECT_TYPE,OWNER_OBJECT_SCHEMA,OWNER_OBJECT_NAME,STATEMENT_NAME,SQL_TEXT FROM performance_schema.prepared_statemments_instances WHERE OWNER_OBJECT_TYPE IS NOT NULL;

· TIMER_PREPARE:執行prepare語句本身消耗的時間。

· COUNT_REPREPARE:該行信息對應的prepare語句在內部被重新編譯的次數,重新編譯prepare語句之後,之前的相關統計信息就不可用了,因爲這些統計信息是作爲語句執行的一部分被聚合到表中的,而不是單獨維護的。

· COUNT_EXECUTE,SUM_TIMER_EXECUTE,MIN_TIMER_EXECUTE,AVG_TIMER_EXECUTE,MAX_TIMER_EXECUTE:執行prepare語句時的相關統計數據。

· SUM_xxx:其餘的SUM_xxx開頭的列與語句統計表中的信息相同,語句統計表後續章節會詳細介紹。

允許執行TRUNCATE TABLE語句,但是TRUNCATE TABLE只是重置prepared_statements_instances表的統計信息列,但是不會刪除該表中的記錄,該表中的記錄會在prepare對象被銷燬釋放的時候自動刪除。

PS:什麼是prepare語句?prepare語句實際上就是一個預編譯語句,先把SQL語句進行編譯,且可以設定參數佔位符(例如:?符號),然後調用時通過用戶變量傳入具體的參數值(叫做變量綁定),如果一個語句需要多次執行而僅僅只是where條件不同,那麼使用prepare語句可以大大減少硬解析的開銷,prepare語句有三個步驟,預編譯prepare語句,執行prepare語句,釋放銷燬prepare語句,prepare語句支持兩種協議,前面已經提到過了,binary協議一般是提供給應用程序的mysql c api接口方式訪問,而文本協議提供給通過客戶端連接到mysql server的方式訪問,下面以文本協議的方式訪問進行演示說明:

· prepare步驟:語法PREPARE stmt_name FROM preparable_stmt,示例:PREPARE stmt FROM'SELECT 1'; 執行了該語句之後,在prepared_statements_instances表中就可以查詢到一個prepare示例對象了;

· execute步驟:語法EXECUTE stmt_name[USING @var_name [, @var_name] …],示例:execute stmt; 返回執行結果爲1,此時在prepared_statements_instances表中的統計信息會進行更新;

· DEALLOCATE PREPARE步驟:語法 {DEALLOCATE | DROP} PREPARE stmt_name,示例:drop prepare stmt; ,此時在prepared_statements_instances表中對應的prepare示例記錄自動刪除。

6.instance 統計表

instance表記錄了哪些類型的對象被檢測。這些表中記錄了事件名稱(提供收集功能的instruments名稱)及其一些解釋性的狀態信息(例如:file_instances表中的FILE_NAME文件名稱和OPEN_COUNT文件打開次數),instance表主要有如下幾個:

· cond_instances:wait sync相關的condition對象實例;

· file_instances:文件對象實例;

· mutex_instances:wait sync相關的Mutex對象實例;

· rwlock_instances:wait sync相關的lock對象實例;

· socket_instances:活躍連接實例。

這些表列出了等待事件中的sync子類事件相關的對象、文件、連接。其中wait sync相關的對象類型有三種:cond、mutex、rwlock。每個實例表都有一個EVENT_NAME或NAME列,用於顯示與每行記錄相關聯的instruments名稱。instruments名稱可能具有多個部分並形成層次結構,詳見 "配置詳解 | performance_schema全方位介紹"

mutex_instances.LOCKED_BY_THREAD_ID和rwlock_instances.WRITE_LOCKED_BY_THREAD_ID列對於排查性能瓶頸或死鎖問題至關重要。

PS:對於mutexes、conditions和rwlocks,在運行時雖然允許修改配置,且配置能夠修改成功,但是有一部分instruments不生效,需要在啓動時配置纔會生效,如果你嘗試着使用一些應用場景來追蹤鎖信息,你可能在這些instance表中無法查詢到相應的信息。

下面對這些表分別進行說明。

(1)cond_instances表

cond_instances表列出了server執行condition instruments 時performance_schema所見的所有condition,condition表示在代碼中特定事件發生時的同步信號機制,使得等待該條件的線程在該condition滿足條件時可以恢復工作。

· 當一個線程正在等待某事發生時,condition NAME列顯示了線程正在等待什麼condition(但該表中並沒有其他列來顯示對應哪個線程等信息),但是目前還沒有直接的方法來判斷某個線程或某些線程會導致condition發生改變。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 02:50:02> select * from cond_instances limit 1;
+----------------------------------+-----------------------+
| NAME                             | OBJECT_INSTANCE_BEGIN |
+----------------------------------+-----------------------+
| wait/synch/cond/sql/COND_manager |              31903008 |
+----------------------------------+-----------------------+
1 row in set (0.00 sec)

cond_instances表字段含義如下:

· NAME:與condition相關聯的instruments名稱;

· OBJECT_INSTANCE_BEGIN:instruments condition的內存地址;

· PS:cond_instances表不允許使用TRUNCATE TABLE語句。

 (2)file_instances表

file_instances表列出執行文件I/O instruments時performance_schema所見的所有文件。如果磁盤上的文件從未打開,則不會在file_instances中記錄。當文件從磁盤中刪除時,它也會從file_instances表中刪除對應的記錄。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 02:53:40> select * from file_instances where OPEN_COUNT>0 limit 1;
+------------------------------------+--------------------------------------+------------+
| FILE_NAME                          | EVENT_NAME                          | OPEN_COUNT |
+------------------------------------+--------------------------------------+------------+
| /data/mysqldata1/innodb_ts/ibdata1 | wait/io/file/innodb/innodb_data_file |          3 |
+------------------------------------+--------------------------------------+------------+
1 row in set (0.00 sec)

file_instances表字段含義如下:

· FILE_NAME:磁盤文件名稱;

· EVENT_NAME:與文件相關聯的instruments名稱;

OPEN_COUNT:文件當前已打開句柄的計數。如果文件打開然後關閉,則打開1次,但OPEN_COUNT列將加一然後減一,因爲OPEN_COUNT列只統計當前已打開的文件句柄數,已關閉的文件句柄會從中減去。要列出server中當前打開的所有文件信息,可以使用where WHERE OPEN_COUNT> 0子句進行查看。

file_instances表不允許使用TRUNCATE TABLE語句。

(3)mutex_instances表

mutex_instances表列出了server執行mutex instruments時performance_schema所見的所有互斥量。互斥是在代碼中使用的一種同步機制,以強制在給定時間內只有一個線程可以訪問某些公共資源。可以認爲mutex保護着這些公共資源不被隨意搶佔。

當在server中同時執行的兩個線程(例如,同時執行查詢的兩個用戶會話)需要訪問相同的資源(例如:文件、緩衝區或某些數據)時,這兩個線程相互競爭,因此第一個成功獲取到互斥體的查詢將會阻塞其他會話的查詢,直到成功獲取到互斥體的會話執行完成並釋放掉這個互斥體,其他會話的查詢才能夠被執行。

需要持有互斥體的工作負載可以被認爲是處於一個關鍵位置的工作,多個查詢可能需要以序列化的方式(一次一個串行)執行這個關鍵部分,但這可能是一個潛在的性能瓶頸。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 03:23:47> select * from mutex_instances limit 1;
+--------------------------------------+-----------------------+---------------------+
| NAME                                 | OBJECT_INSTANCE_BEGIN | LOCKED_BY_THREAD_ID |
+--------------------------------------+-----------------------+---------------------+
| wait/synch/mutex/mysys/THR_LOCK_heap |              32576832 |                NULL |
+--------------------------------------+-----------------------+---------------------+
1 row in set (0.00 sec)

mutex_instances表字段含義如下:

· NAME:與互斥體關聯的instruments名稱;

· OBJECT_INSTANCE_BEGIN:mutex instruments實例的內存地址;

· LOCKED_BY_THREAD_ID:當一個線程當前持有一個互斥鎖定時,LOCKED_BY_THREAD_ID列顯示持有線程的THREAD_ID,如果沒有被任何線程持有,則該列值爲NULL。

mutex_instances表不允許使用TRUNCATE TABLE語句。

對於代碼中的每個互斥體,performance_schema提供了以下信息:

· setup_instruments表列出了instruments名稱,這些互斥體都帶有wait/synch/mutex/前綴;

· 當server中一些代碼創建了一個互斥量時,在mutex_instances表中會添加一行對應的互斥體信息(除非無法再創建mutex instruments instance就不會添加行)。OBJECT_INSTANCE_BEGIN列值是互斥體的唯一標識屬性;

· 當一個線程嘗試獲取已經被某個線程持有的互斥體時,在events_waits_current表中會顯示嘗試獲取這個互斥體的線程相關等待事件信息,顯示它正在等待的mutex 類別(在EVENT_NAME列中可以看到),並顯示正在等待的mutex instance(在OBJECT_INSTANCE_BEGIN列中可以看到);

· 當線程成功鎖定(持有)互斥體時: 

* events_waits_current表中可以查看到當前正在等待互斥體的線程時間信息(例如:TIMER_WAIT列表示已經等待的時間) ;

* 已完成的等待事件將添加到events_waits_history和events_waits_history_long表中 ;

* mutex_instances表中的THREAD_ID列顯示該互斥體現在被哪個線程持有。

· 當持有互斥體的線程釋放互斥體時,mutex_instances表中對應互斥體行的THREAD_ID列被修改爲NULL;

· 當互斥體被銷燬時,從mutex_instances表中刪除相應的互斥體行。

通過對以下兩個表執行查詢,可以實現對應用程序的監控或DBA可以檢測到涉及互斥體的線程之間的瓶頸或死鎖信息(events_waits_current可以查看到當前正在等待互斥體的線程信息,mutex_instances可以查看到當前某個互斥體被哪個線程持有)。

(4)rwlock_instances表

rwlock_instances表列出了server執行rwlock instruments時performance_schema所見的所有rwlock(讀寫鎖)實例。rwlock是在代碼中使用的同步機制,用於強制在給定時間內線程可以按照某些規則訪問某些公共資源。可以認爲rwlock保護着這些資源不被其他線程隨意搶佔。訪問模式可以是共享的(多個線程可以同時持有共享讀鎖)、排他的(同時只有一個線程在給定時間可以持有排他寫鎖)或共享獨佔的(某個線程持有排他鎖定時,同時允許其他線程執行不一致性讀)。共享獨佔訪問被稱爲sxlock,該訪問模式在讀寫場景下可以提高併發性和可擴展性。

根據請求鎖的線程數以及所請求的鎖的性質,訪問模式有:獨佔模式、共享獨佔模式、共享模式、或者所請求的鎖不能被全部授予,需要先等待其他線程完成並釋放。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 10:28:45> select * from rwlock_instances limit 1;
+-------------------------------------------------------+-----------------------+---------------------------+----------------------+
| NAME                                                  | OBJECT_INSTANCE_BEGIN | WRITE_LOCKED_BY_THREAD_ID | READ_LOCKED_BY_COUNT |
+-------------------------------------------------------+-----------------------+---------------------------+----------------------+
| wait/synch/rwlock/session/LOCK_srv_session_collection |              31856216 |                      NULL |                    0 |
+-------------------------------------------------------+-----------------------+---------------------------+----------------------+
1 row in set (0.00 sec)

rwlock_instances表字段含義如下:

· NAME:與rwlock關聯的instruments名稱;

· OBJECT_INSTANCE_BEGIN:讀寫鎖實例的內存地址;

· WRITE_LOCKED_BY_THREAD_ID:當一個線程當前在獨佔(寫入)模式下持有一個rwlock時,WRITE_LOCKED_BY_THREAD_ID列可以查看到持有該鎖的線程THREAD_ID,如果沒有被任何線程持有則該列爲NULL;

· READ_LOCKED_BY_COUNT:當一個線程在共享(讀)模式下持有一個rwlock時,READ_LOCKED_BY_COUNT列值增加1,所以該列只是一個計數器,不能直接用於查找是哪個線程持有該rwlock,但它可以用來查看是否存在一個關於rwlock的讀爭用以及查看當前有多少個讀模式線程處於活躍狀態。

rwlock_instances表不允許使用TRUNCATE TABLE語句。

通過對以下兩個表執行查詢,可以實現對應用程序的監控或DBA可以檢測到涉及鎖的線程之間的一些瓶頸或死鎖信息:

· events_waits_current:查看線程正在等待什麼rwlock;

· rwlock_instances:查看當前rwlock行的一些鎖信息(獨佔鎖被哪個線程持有,共享鎖被多少個線程持有等)。

注意:rwlock_instances表中的信息只能查看到持有寫鎖的線程ID,但是不能查看到持有讀鎖的線程ID,因爲寫鎖WRITE_LOCKED_BY_THREAD_ID字段記錄的是線程ID,讀鎖只有一個READ_LOCKED_BY_COUNT字段來記錄讀鎖被多少個線程持有。

(5) socket_instances表

socket_instances表列出了連接到MySQL server的活躍連接的實時快照信息。對於每個連接到mysql server中的TCP/IP或Unix套接字文件連接都會在此表中記錄一行信息。(套接字統計表socket_summary_by_event_name和socket_summary_by_instance中提供了一些附加信息,例如像socket操作以及網絡傳輸和接收的字節數)。

套接字instruments具有wait/io/socket/sql/socket_type形式的名稱,如下:

· server 監聽一個socket以便爲網絡連接協議提供支持。對於監聽TCP/IP或Unix套接字文件連接來說,分別有一個名爲server_tcpip_socket和server_unix_socket的socket_type值,組成對應的instruments名稱;

· 當監聽套接字檢測到連接時,srever將連接轉移給一個由單獨線程管理的新套接字。新連接線程的instruments具有client_connection的socket_type值,組成對應的instruments名稱;

· 當連接終止時,在socket_instances表中對應的連接信息行被刪除。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 10:49:34> select * from socket_instances;
+----------------------------------------+-----------------------+-----------+-----------+--------------------+-------+--------+
| EVENT_NAME                             | OBJECT_INSTANCE_BEGIN | THREAD_ID | SOCKET_ID | IP                 | PORT  | STATE  |
+----------------------------------------+-----------------------+-----------+-----------+--------------------+-------+--------+
| wait/io/socket/sql/server_tcpip_socket |            110667200  |        1  |        32 | ::                 |  3306 | ACTIVE |
| wait/io/socket/sql/server_unix_socket  |            110667520  |        1  |        34 |                    |     0 | ACTIVE |
| wait/io/socket/sql/client_connection   |            110667840  |        45 |        51 | ::ffff:10.10.20.15 | 56842 | ACTIVE |
| wait/io/socket/sql/client_connection   |            110668160  |        46 |        53 |                    |    0  | ACTIVE |
+----------------------------------------+-----------------------+-----------+-----------+--------------------+-------+--------+
4 rows in set (0.00 sec)

socket_instances表字段含義如下:

· EVENT_NAME:生成事件信息的instruments 名稱。與setup_instruments表中的NAME值對應;

· OBJECT_INSTANCE_BEGIN:此列是套接字實例對象的唯一標識。該值是內存中對象的地址;

· THREAD_ID:由server分配的內部線程標識符,每個套接字都由單個線程進行管理,因此每個套接字都可以映射到一個server線程(如果可以映射的話);

· SOCKET_ID:分配給套接字的內部文件句柄;

· IP:客戶端IP地址。該值可以是IPv4或IPv6地址,也可以是空串,表示這是一個Unix套接字文件連接;

· PORT:TCP/IP端口號,取值範圍爲0〜65535;

· STATE:套接字狀態,有效值爲:IDLE或ACTIVE。跟蹤活躍socket連接的等待時間使用相應的socket instruments。跟着空閒socket連接的等待時間使用一個叫做idle的socket instruments。如果一個socket正在等待來自客戶端的請求,則該套接字此時處於空閒狀態。當套接字處於空閒時,在socket_instances表中對應socket線程的信息中的STATE列值從ACTIVE狀態切換到IDLE。EVENT_NAME值保持不變,但是instruments的時間收集功能被暫停。同時在events_waits_current表中記錄EVENT_NAME列值爲idle的一行事件信息。當這個socket接收到下一個請求時,idle事件被終止,socket instance從空閒狀態切換到活動狀態,並恢復套接字連接的時間收集功能。

socket_instances表不允許使用TRUNCATE TABLE語句。

IP:PORT列組合值可用於標識一個連接。該組合值在events_waits_xxx表的“OBJECT_NAME”列中使用,以標識這些事件信息是來自哪個套接字連接的:

· 對於Unix domain套接字(server_unix_socket)的server端監聽器,端口爲0,IP爲空串;

· 對於通過Unix domain套接字(client_connection)的客戶端連接,端口爲0,IP爲空串;

· 對於TCP/IP server套接字(server_tcpip_socket)的server端監聽器,端口始終爲主端口(例如3306),IP始終爲0.0.0.0;

· 對於通過TCP/IP 套接字(client_connection)的客戶端連接,端口是server隨機分配的,但不會爲0值. IP是源主機的IP(127.0.0.1或本地主機的:: 1)。

 7.鎖對象記錄表

performance_schema通過如下表來記錄相關的鎖信息:

· metadata_locks:元數據鎖的持有和請求記錄;

· table_handles:表鎖的持有和請求記錄。

(1)metadata_locks表

Performance Schema通過metadata_locks表記錄元數據鎖信息:

· 已授予的鎖(顯示哪些會話擁有當前元數據鎖);

· 已請求但未授予的鎖(顯示哪些會話正在等待哪些元數據鎖);

· 已被死鎖檢測器檢測到並被殺死的鎖,或者鎖請求超時正在等待鎖請求會話被丟棄。

這些信息使您能夠了解會話之間的元數據鎖依賴關係。不僅可以看到會話正在等待哪個鎖,還可以看到當前持有該鎖的會話ID。

metadata_locks表是隻讀的,無法更新。默認保留行數會自動調整,如果要配置該表大小,可以在server啓動之前設置系統變量performance_schema_max_metadata_locks的值。

元數據鎖instruments使用wait/lock/metadata/sql/mdl,默認未開啓。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 04:55:42> select * from metadata_locks\G;
*************************** 1. row ***************************
      OBJECT_TYPE: TABLE
    OBJECT_SCHEMA: xiaoboluo
      OBJECT_NAME: test
OBJECT_INSTANCE_BEGIN: 140568048055488
        LOCK_TYPE: SHARED_READ
    LOCK_DURATION: TRANSACTION
      LOCK_STATUS: GRANTED
          SOURCE: sql_parse.cc:6031
  OWNER_THREAD_ID: 46
  OWNER_EVENT_ID: 49
1 rows in set (0.00 sec)

metadata_locks表字段含義如下:

· OBJECT_TYPE:元數據鎖子系統中使用的鎖類型(類似setup_objects表中的OBJECT_TYPE列值):有效值爲:GLOBAL、SCHEMA、TABLE、FUNCTION、PROCEDURE、TRIGGER(當前未使用)、EVENT、COMMIT、USER LEVEL LOCK、TABLESPACE、LOCKING SERVICE,USER LEVEL LOCK值表示該鎖是使用GET_LOCK()函數獲取的鎖。LOCKING SERVICE值表示使用鎖服務獲取的鎖;

· OBJECT_SCHEMA:該鎖來自於哪個庫級別的對象;

· OBJECT_NAME:instruments對象的名稱,表級別對象;

· OBJECT_INSTANCE_BEGIN:instruments對象的內存地址;

· LOCK_TYPE:元數據鎖子系統中的鎖類型。有效值爲:INTENTION_EXCLUSIVE、SHARED、SHARED_HIGH_PRIO、SHARED_READ、SHARED_WRITE、SHARED_UPGRADABLE、SHARED_NO_WRITE、SHARED_NO_READ_WRITE、EXCLUSIVE;

· LOCK_DURATION:來自元數據鎖子系統中的鎖定時間。有效值爲:STATEMENT、TRANSACTION、EXPLICIT,STATEMENT和TRANSACTION值分別表示在語句或事務結束時會釋放的鎖。EXPLICIT值表示可以在語句或事務結束時被會保留,需要顯式釋放的鎖,例如:使用FLUSH TABLES WITH READ LOCK獲取的全局鎖;

· LOCK_STATUS:元數據鎖子系統的鎖狀態。有效值爲:PENDING、GRANTED、VICTIM、TIMEOUT、KILLED、PRE_ACQUIRE_NOTIFY、POST_RELEASE_NOTIFY。performance_schema根據不同的階段更改鎖狀態爲這些值;

· SOURCE:源文件的名稱,其中包含生成事件信息的檢測代碼行號;

· OWNER_THREAD_ID:請求元數據鎖的線程ID;

· OWNER_EVENT_ID:請求元數據鎖的事件ID。

performance_schema如何管理metadata_locks表中記錄的內容(使用LOCK_STATUS列來表示每個鎖的狀態):

· 當請求立即獲取元數據鎖時,將插入狀態爲GRANTED的鎖信息行;

· 當請求元數據鎖不能立即獲得時,將插入狀態爲PENDING的鎖信息行;

· 當之前請求不能立即獲得的鎖在這之後被授予時,其鎖信息行狀態更新爲GRANTED;

· 釋放元數據鎖時,對應的鎖信息行被刪除;

· 當一個pending狀態的鎖被死鎖檢測器檢測並選定爲用於打破死鎖時,這個鎖會被撤銷,並返回錯誤信息(ER_LOCK_DEADLOCK)給請求鎖的會話,鎖狀態從PENDING更新爲VICTIM;

· 當待處理的鎖請求超時,會返回錯誤信息(ER_LOCK_WAIT_TIMEOUT)給請求鎖的會話,鎖狀態從PENDING更新爲TIMEOUT;

· 當已授予的鎖或掛起的鎖請求被殺死時,其鎖狀態從GRANTED或PENDING更新爲KILLED;

· VICTIM,TIMEOUT和KILLED狀態值停留時間很簡短,當一個鎖處於這個狀態時,那麼表示該鎖行信息即將被刪除(手動執行SQL可能因爲時間原因查看不到,可以使用程序抓取);

· PRE_ACQUIRE_NOTIFY和POST_RELEASE_NOTIFY狀態值停留事件都很簡短,當一個鎖處於這個狀態時,那麼表示元數據鎖子系統正在通知相關的存儲引擎該鎖正在執行分配或釋。這些狀態值在5.7.11版本中新增。

metadata_locks表不允許使用TRUNCATE TABLE語句。

(2)table_handles表

performance_schema通過table_handles表記錄表鎖信息,以對當前每個打開的表所持有的表鎖進行追蹤記錄。table_handles輸出表鎖instruments採集的內容。這些信息顯示server中已打開了哪些表,鎖定方式是什麼以及被哪個會話持有。

table_handles表是隻讀的,不能更新。默認自動調整表數據行大小,如果要顯式指定個,可以在server啓動之前設置系統變量performance_schema_max_table_handles的值。

對應的instruments爲wait/io/table/sql/handler和wait/lock/table/sql/handler,默認開啓。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 05:47:55> select * from table_handles;
+-------------+---------------+-------------+-----------------------+-----------------+----------------+---------------+---------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME | OBJECT_INSTANCE_BEGIN | OWNER_THREAD_ID | OWNER_EVENT_ID | INTERNAL_LOCK | EXTERNAL_LOCK |
+-------------+---------------+-------------+-----------------------+-----------------+----------------+---------------+---------------+
| TABLE       | xiaoboluo     | test        |      140568038528544  |              0  |              0 | NULL          | NULL          |
+-------------+---------------+-------------+-----------------------+-----------------+----------------+---------------+---------------+
1 row in set (0.00 sec)

table_handles表字段含義如下:

· OBJECT_TYPE:顯示handles鎖的類型,表示該表是被哪個table handles打開的;

· OBJECT_SCHEMA:該鎖來自於哪個庫級別的對象;

· OBJECT_NAME:instruments對象的名稱,表級別對象;

· OBJECT_INSTANCE_BEGIN:instruments對象的內存地址;

· OWNER_THREAD_ID:持有該handles鎖的線程ID;

· OWNER_EVENT_ID:觸發table handles被打開的事件ID,即持有該handles鎖的事件ID;

· INTERNAL_LOCK:在SQL級別使用的表鎖。有效值爲:READ、READ WITH SHARED LOCKS、READ HIGH PRIORITY、READ NO INSERT、WRITE ALLOW WRITE、WRITE CONCURRENT INSERT、WRITE LOW PRIORITY、WRITE。有關這些鎖類型的詳細信息,請參閱include/thr_lock.h源文件;

· EXTERNAL_LOCK:在存儲引擎級別使用的表鎖。有效值爲:READ EXTERNAL、WRITE EXTERNAL。

table_handles表不允許使用TRUNCATE TABLE語句。

02

屬性統計表

1. 連接信息統計表

當客戶端連接到MySQL server時,它的用戶名和主機名都是特定的。performance_schema按照帳號、主機、用戶名對這些連接的統計信息進行分類並保存到各個分類的連接信息表中,如下:

· accounts:按照user@host的形式來對每個客戶端的連接進行統計;

· hosts:按照host名稱對每個客戶端連接進行統計;

· users:按照用戶名對每個客戶端連接進行統計。

連接信息表accounts中的user和host字段含義與mysql系統數據庫中的MySQL grant表(user表)中的字段含義類似。

每個連接信息表都有CURRENT_CONNECTIONS和TOTAL_CONNECTIONS列,用於跟蹤連接的當前連接數和總連接數。對於accounts表,每個連接在表中每行信息的唯一標識爲USER+HOST,但是對於users表,只有一個user字段進行標識,而hosts表只有一個host字段用於標識。

performance_schema還統計後臺線程和無法驗證用戶的連接,對於這些連接統計行信息,USER和HOST列值爲NULL。

當客戶端與server端建立連接時,performance_schema使用適合每個表的唯一標識值來確定每個連接表中如何進行記錄。如果缺少對應標識值的行,則新添加一行。然後,performance_schema會增加該行中的CURRENT_CONNECTIONS和TOTAL_CONNECTIONS列值。

當客戶端斷開連接時,performance_schema將減少對應連接的行中的CURRENT_CONNECTIONS列,保留TOTAL_CONNECTIONS列值。

這些連接表都允許使用TRUNCATE TABLE語句:

· 當行信息中CURRENT_CONNECTIONS 字段值爲0時,執行truncate語句會刪除這些行;

· 當行信息中CURRENT_CONNECTIONS 字段值大於0時,執行truncate語句不會刪除這些行,TOTAL_CONNECTIONS字段值被重置爲CURRENT_CONNECTIONS字段值;

· 依賴於連接表中信息的summary表在對這些連接表執行truncate時會同時被隱式地執行truncate,performance_schema維護着按照accounts,hosts或users統計各種事件統計表。這些表在名稱包括:_summary_by_account,_summary_by_host,*_summary_by_user

連接統計信息表允許使用TRUNCATE TABLE。它會同時刪除統計表中沒有連接的帳戶,主機或用戶對應的行,重置有連接的帳戶,主機或用戶對應的行的並將其他行的CURRENT_CONNECTIONS和TOTAL_CONNECTIONS列值。

truncate *_summary_global統計表也會隱式地truncate其對應的連接和線程統計表中的信息。例如:truncate events_waits_summary_global_by_event_name會隱式地truncate按照帳戶,主機,用戶或線程統計的等待事件統計表。

下面對這些表分別進行介紹。

(1)accounts表

accounts表包含連接到MySQL server的每個account的記錄。對於每個帳戶,沒個user+host唯一標識一行,每行單獨計算該帳號的當前連接數和總連接數。server啓動時,表的大小會自動調整。要顯式設置表大小,可以在server啓動之前設置系統變量performance_schema_accounts_size的值。該系統變量設置爲0時,表示禁用accounts表的統計信息功能。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 09:34:49> select * from accounts;
+-------+-------------+---------------------+-------------------+
| USER  | HOST        | CURRENT_CONNECTIONS | TOTAL_CONNECTIONS |
+-------+-------------+---------------------+-------------------+
| NULL  | NULL        |                  41 |                45 |
| qfsys | 10.10.20.15 |                  1 |                1 |
| admin | localhost  |                 1 |                1 |
+-------+-------------+---------------------+-------------------+
3 rows in set (0.00 sec)

accounts表字段含義如下:

· USER:某連接的客戶端用戶名。如果是一個內部線程創建的連接,或者是無法驗證的用戶創建的連接,則該字段爲NULL;

· HOST:某連接的客戶端主機名。如果是一個內部線程創建的連接,或者是無法驗證的用戶創建的連接,則該字段爲NULL;

· CURRENT_CONNECTIONS:某帳號的當前連接數;

· TOTAL_CONNECTIONS:某帳號的總連接數(新增加一個連接累計一個,不會像當前連接數那樣連接斷開會減少)。

(2)users表

users表包含連接到MySQL server的每個用戶的連接信息,每個用戶一行。該表將針對用戶名作爲唯一標識進行統計當前連接數和總連接數,server啓動時,表的大小會自動調整。要顯式設置該表大小,可以在server啓動之前設置系統變量performance_schema_users_size的值。該變量設置爲0時表示禁用users統計信息。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 09:50:01> select * from users;
+-------+---------------------+-------------------+
| USER  | CURRENT_CONNECTIONS | TOTAL_CONNECTIONS |
+-------+---------------------+-------------------+
| NULL  |                  41 |                45 |
| qfsys |                  1 |                1 |
| admin |                  1 |                1 |
+-------+---------------------+-------------------+
3 rows in set (0.00 sec)

users表字段含義如下:

· USER:某個連接的用戶名,如果是一個內部線程創建的連接,或者是無法驗證的用戶創建的連接,則該字段爲NULL;

· CURRENT_CONNECTIONS:某用戶的當前連接數;

· TOTAL_CONNECTIONS:某用戶的總連接數。

(3)hosts表

hosts表包含客戶端連接到MySQL server的主機信息,一個主機名對應一行記錄,該錶針對主機作爲唯一標識進行統計當前連接數和總連接數。server啓動時,表的大小會自動調整。要顯式設置該表大小,可以在server啓動之前設置系統變量performance_schema_hosts_size的值。如果該變量設置爲0,則表示禁用hosts表統計信息。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 09:49:41> select * from hosts;
+-------------+---------------------+-------------------+
| HOST        | CURRENT_CONNECTIONS | TOTAL_CONNECTIONS |
+-------------+---------------------+-------------------+
| NULL        |                  41 |                45 |
| 10.10.20.15 |                  1 |                1 |
| localhost  |                  1 |                1 |
+-------------+---------------------+-------------------+
3 rows in set (0.00 sec)

hosts表字段含義如下:

· HOST:某個連接的主機名,如果是一個內部線程創建的連接,或者是無法驗證的用戶創建的連接,則該字段爲NULL;

· CURRENT_CONNECTIONS:某主機的當前連接數;

· TOTAL_CONNECTIONS:某主機的總連接數。

2. 連接屬性統計表

應用程序可以使用一些鍵/值對生成一些連接屬性,在對mysql server創建連接時傳遞給server。對於C API,使用mysql_options()和mysql_options4()函數定義屬性集。其他MySQL連接器可以使用一些自定義連接屬性方法。

連接屬性記錄在如下兩張表中:

· session_account_connect_attrs:記錄當前會話及其相關聯的其他會話的連接屬性;

· session_connect_attrs:所有會話的連接屬性。

MySQL允許應用程序引入新的連接屬性,但是以下劃線(_)開頭的屬性名稱保留供內部使用,應用程序不要創建這種格式的連接屬性。以確保內部的連接屬性不會與應用程序創建的連接屬性相沖突。

一個連接可見的連接屬性集合取決於與mysql server建立連接的客戶端平臺類型和MySQL連接的客戶端類型。

· libmysqlclient客戶端庫(在MySQL和MySQL Connector / C發行版中提供)提供以下屬性: 

* _client_name:客戶端名稱(客戶端庫的libmysql) 
* _client_version:客戶端libmysql庫版本 
* _os:客戶端操作系統類型(例如Linux,Win64) 
* _pid:客戶端進程ID
* _platform:客戶端機器平臺(例如,x86_64) 
* _thread:客戶端線程ID(僅適用於Windows)




· MySQL Connector/J定義瞭如下屬性:

* _client_license:連接器許可證類型 
* _runtime_vendor:Java運行環境(JRE)供應商名稱 
* _runtime_version:Java運行環境(JRE)版本

· MySQL Connector/Net定義瞭如下屬性: 

* _client_version:客戶端庫版本 
* _os:操作系統類型(例如Linux,Win64) 
* _pid:客戶端進程ID
* _platform:客戶端機器平臺(例如,x86_64) 
* _program_name:客戶端程序名稱 
* _thread:客戶端線程ID(僅適用於Windows)




· PHP定義的屬性依賴於編譯的屬性: 

* 使用libmysqlclient編譯:php連接的屬性集合使用標準libmysqlclient屬性,參見上文 
* 使用mysqlnd編譯:只有_client_name屬性,值爲mysqlnd

· 許多MySQL客戶端程序設置的屬性值與客戶端名稱相等的一個program_name屬性。例如:mysqladmin和mysqldump分別將program_name連接屬性設置爲mysqladmin和mysqldump,另外一些MySQL客戶端程序還定義了附加屬性: 

* mysqlbinlog定義了_client_role屬性,值爲binary_log_listener 
* 複製slave連接的program_name屬性值被定義爲mysqld、定義了_client_role屬性,值爲binary_log_listener、_client_replication_channel_name屬性,值爲通道名稱字符串 
* FEDERATED存儲引擎連接的program_name屬性值被定義爲mysqld、定義了_client_role屬性,值爲federated_storage

從客戶端發送到服務器的連接屬性數據量存在限制:客戶端在連接之前客戶端有一個自己的固定長度限制(不可配置)、在客戶端連接server時服務端也有一個固定長度限制、以及在客戶端連接server時的連接屬性值在存入performance_schema中時也有一個可配置的長度限制。

對於使用C API啓動的連接,libmysqlclient庫對客戶端上的客戶端面連接屬性數據的統計大小的固定長度限制爲64KB:超出限制時調用mysql_options()函數會報CR_INVALID_PARAMETER_NO錯誤。其他MySQL連接器可能會設置自己的客戶端面的連接屬性長度限制。

在服務器端面,會對連接屬性數據進行長度檢查:

· server只接受的連接屬性數據的統計大小限制爲64KB。如果客戶端嘗試發送超過64KB(正好是一個表所有字段定義長度的總限制長度)的屬性數據,則server將拒絕該連接;

· 對於已接受的連接,performance_schema根據performance_schema_session_connect_attrs_size系統變量的值檢查統計連接屬性大小。如果屬性大小超過此值,則會執行以下操作: 

* performance_schema截斷超過長度的屬性數據,並增加Performance_schema_session_connect_attrs_lost狀態變量值,截斷一次增加一次,即該變量表示連接屬性被截斷了多少次 
* 如果log_error_verbosity系統變量設置值大於1,則performance_schema還會將錯誤信息寫入錯誤日誌:

[Warning] Connection attributes of length N were truncated

(1) session_account_connect_attrs表

應用程序可以使用mysql_options()和mysql_options4()C API函數在連接時提供一些要傳遞到server的鍵值對連接屬性。

session_account_connect_attrs表僅包含當前連接及其相關聯的其他連接的連接屬性。要查看所有會話的連接屬性,請查看session_connect_attrs表。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 11:00:45> select * from session_account_connect_attrs;
+----------------+-----------------+----------------+------------------+
| PROCESSLIST_ID | ATTR_NAME      | ATTR_VALUE    | ORDINAL_POSITION |
+----------------+-----------------+----------------+------------------+
|              4 | _os            | linux-glibc2.5 |                0 |
|              4 | _client_name    | libmysql      |                1 |
|              4 | _pid            | 3766          |                2 |
|              4 | _client_version | 5.7.18        |                3 |
|              4 | _platform      | x86_64        |                4 |
|              4 | program_name    | mysql          |                5 |
+----------------+-----------------+----------------+------------------+
6 rows in set (0.00 sec)

session_account_connect_attrs表字段含義:

· PROCESSLIST_ID:會話的連接標識符,與show processlist結果中的ID字段相同;

· ATTR_NAME:連接屬性名稱;

· ATTR_VALUE:連接屬性值;

· ORDINAL_POSITION:將連接屬性添加到連接屬性集的順序。

session_account_connect_attrs表不允許使用TRUNCATE TABLE語句。

(2)session_connect_attrs表

表字段含義與session_account_connect_attrs表相同,但是該表是保存所有連接的連接屬性表。

我們先來看看錶中記錄的統計信息是什麼樣子的。

admin@localhost : performance_schema 11:05:51> select * from session_connect_attrs;
+----------------+----------------------------------+---------------------+------------------+
| PROCESSLIST_ID | ATTR_NAME                        | ATTR_VALUE          | ORDINAL_POSITION |
+----------------+----------------------------------+---------------------+------------------+
|              3 | _os                              | linux-glibc2.5      |                0 |
|              3 | _client_name                    | libmysql            |                1 |
......
14 rows in set (0.01 sec)

表字段含義與session_account_connect_attrs表字段含義相同。

- END -

下期將爲大家分享 《複製狀態與變量記錄表 | performance_schema全方位介紹》 ,謝謝你的閱讀,我們下期不見不散!

| 作者簡介

羅小波·數據庫技術專家

《千金良方——MySQL性能優化金字塔法則》、《數據生態:MySQL複製技術與生產實踐》作者之一。熟悉MySQL體系結構,擅長數據庫的整體調優,喜好專研開源技術,並熱衷於開源技術的推廣,在線上線下做過多次公開的數據庫專題分享,發表過近100篇數據庫相關的研究文章。

全文完。

Enjoy MySQL :)

葉老師的「MySQL核心優化」大課已升級到MySQL 8.0,掃碼開啓MySQL 8.0修行之旅吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章