Memory Instruments如何被注册到PSI中(一)
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。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫