Memory Instruments如何被注册到PSI中

发布时间 2023-08-02 17:03:25作者: 吃饭端住碗

SETUP_INSTRUMENTS表

首先看一下PERFORMANCE_SCHEMA.SETUP_INSTRUMENTS的表结构:

CREATE TABLE `setup_instruments` (
  `NAME` varchar(128) NOT NULL,
  `ENABLED` enum('YES','NO') NOT NULL,
  `TIMED` enum('YES','NO') DEFAULT NULL,
  `PROPERTIES` set('singleton','progress','user','global_statistics','mutable') NOT NULL,
  `VOLATILITY` int NOT NULL,
  `DOCUMENTATION` longtext,
  PRIMARY KEY (`NAME`)
) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

PERFORMANCE_SCHEMA.SETUP_INSTRUMENTS表定义代码:

SETUP_INSTRUMENTS表中的行数据主要是通过row_setup_instruments类来存取的,而元数据主要存储在PFS_instr_class对象中,PFS_instr_class对象描述了instrument的信息,关系图如下:

更新PERFORMANCE_SCHEMA.SETUP_INSTRUMENTS表的`ENABLED`和`TIMED`会更新PFS_instr_class对象的`m_enabled`和`m_timed`属性;PERFORMANCE_SCHEMA.SETUP_INSTRUMENTS表的其他字段不允许更新。

PERFORMANCE_SCHEMA.SETUP_INSTRUMENTS表数据和PFS_instr_class对象属性的对应关系:

  • SETUP_INSTRUMENTS.NAME=PFS_instr_class.m_name
  • SETUP_INSTRUMENTS.ENABLED=PFS_instr_class.m_enabled
  • SETUP_INSTRUMENTS.TIMED=PFS_instr_class.m_timed
  • SETUP_INSTRUMENTS.PROPERTIES=预定义的properties,有5种:is_singleton、is_mutable、is_progress、is_user、is_global
  • SETUP_INSTRUMENTS.VOLATILITY=PFS_instr_class.m_volatility
  • SETUP_INSTRUMENTS.DOCUMENTATION=PFS_instr_class.m_documentation

Memory Instruments注册到PSI接口中

被注册的PSI Memory Info

PSI_memory_info_v1对象描述了内存相关instruments的元数据信息。

需要被注册的PSI_memory_info_v1实例被放到all_server_memory数组中被统一注册,关系结构如图:

 

all_server_memory数组中的PSI_memory_info_v1(PSI_memory_key)实例如下(sql类别):

其中PSI_memory_info_v1的m_key为需要被注册的memory key,是PSI_memory_key类的实例对象,只有被注册的PSI_memory_key对象才能被监控,PSI_memory_key实例已经被预定义:

m_name为需要被注册的内存instrument的名称。m_flags为需要被注册的内存instrument的标记,比如标记这个instrument全局的还是和线程相关的,如果是GLOBAL的,后面进行内存监控的统计信息汇聚时,只进行GLOBAL汇聚,而不会进行基于thread/account/user/host的汇聚。

PSI接口

PFS接口在mysqld启动的时候通过initialize_performance_schema函数初始化,通过set_psi_memory_service来挂上内存相关PSI的hook。

PSI_memory_bootstrap是Performance schema内存接口的入口,可以通过该入口来获取不同版本的内存接口(目前使用VERSION_2):

获取内存接口:

psi_memory_hook则是PSI_memory_bootstrap对象的指针。

在initialize_performance_schema函数中初始化内存入口对象:

后续则通过set_psi_memory_service来挂上内存相关PFS的hook,即获取VERSION_2的内存接口:

获取PSI_memory_service_v2内存接口对象:

其中在PSI_memory_service_v2类中,共包含了5种接口,包含了注册内存、内存分配、内存回收等:

PSI_memory_service_v2对象的实例数组pfs_memory_service_v2中也定义了5个函数,分别对应5个接口:

后续则是通过init_server_psi_keys将instruments注册到接口中进行监控。有不同类别的instruments,比如sql类别内存相关的instruments的注册是通过register_server_memory_keys函数来进行:

register_server_memory_keys函数的实现:

client类别的instrument keys则是通过init_client_psi_keys函数来注册:

可以在performance_schema.setup_instruments表中看到相关类别的keys:

后续不管是哪个类别的instruments都是通过mysql_memory_register函数将相关的PSI_memory_info_v1实例数组注册到接口中,如:

随后调用PSI_memory_service_v2类中的注册接口函数pfs_register_memory_vc

在pfs_register_memory_vc接口函数中最终调用REGISTER_BODY_V1宏中的build_prefix来构建instruments。