MySQL源码详解三 performance_schema接口实现的一些主意事项

来源:互联网 发布:文明太空 知乎 编辑:程序博客网 时间:2024/04/27 14:46

  
 看PERFORMANCE_SCHEMA的默认实现的代码之前先看一下他的接口设计思路,下面截选出自pfs.cc的注释


  PERFORMANCE_SCHEMA是一种内省服务端运行时内部执行情况的办法,INFORMATION_SCHEMA主要用来观察数据库元信息的,而他专注于数据库的表现信息
  对于用户来说他的表现形势就是一个专用的数据库,叫做PERFORMANCE_SCHEMA,其中的表可以查到服务器内部的状态或事改变他的配置
  对于实现来说,它是一个专注于收集服务器端测量信息的存储引擎
  他对不同的需求、不同的组件暴露了不同的接口
  但是他的实现必须满足这个原则:他的目标是监控服务器的执行,必须对服务器本身的行为不能有任何影响,这些影响主要包括:
  1.不能影响编译器,也就是不能增加SQL的种类、语法等
  2.所有的实现函数必须返回void并且不能有任何异常影响程序的执行

  3.所有实现类不能占用任何抢占资源例如锁、信号量
  4.不能在程序开始之后分配任何资源,必须在MySQL的主流程之情把资源都分配好(看了这条约束,之前为什么要有pre_initialize_performance_schema这个方法,而且写在所有启动程序前面,并且几乎都是全局的变量、数组就可以理解了)

  下面说一下MySQL默认的实现,主要包括两层:
  1.暴露了performance schema仪器类原始测量函数的底层接口(ABI)。代码主要在mysql/psi/psi.h里面。
  2.一个抽象过的API层,提供了很多封装之后的测量函数。代码主要在mysql/psi/mutex_mutex.h和mysql/psi/mutex_file.h中。前者主要是测量互斥锁、读写锁和信号量,后者主要是测量文件IO的

  而每个仪器的测量点的API编程模式通常是首选通知performance schema开始测量了,接着执行测量的代码,最后告诉performance schema测量完成。第一步中会返回一个locker,例如

@verbatim
static inline int mysql_mutex_lock(
  mysql_mutex_t *that, myf flags, const char *src_file, uint src_line)
{
  int result;
  struct PSI_mutex_locker_state state;
  struct PSI_mutex_locker *locker= NULL;


  ............... (a)
  locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->p_psi, PSI_MUTEX_LOCK,
                                           locker, src_file, src_line);


  ............... (b)
  result= pthread_mutex_lock(&that->m_mutex);


  ............... (c)
  PSI_MUTEX_CALL(end_mutex_wait)(locker, result);


  return result;
}


被一个仪器测量的事件包含了很多属性,用向量来表示,每个维度的值代表了一种属性

一个事件的每次操作会创建一个零时对象PFS_wait_locker,在仪器调用start_wait()之前被创建,并在end_wait()之后被销毁,PFS_wait_locker本身包含了一个他等待的实例的指针(m_target)。

仪器对象实例包涵一个指向实现类的一个指针,用仪器名来代替,例如"wait/sync/mutex/sql/LOCK_open"

以对象实例和记录记录为单位的话,不同buffer的指针定义了一个对象实例图。
例如,假设下面的场景
一个互斥锁M被一个仪器类监视,仪器名为"wait/sync/mutex/sql/M",这种锁被实例化了两次,叫做M-1和M-2,线程T_A和T_B锁M-1,T_C和T_D锁M-2,那么performance schema将会记录下面这些数据:
  - EVENTS_WAITS_CURRENT 有4行,每行代表一个使用互斥锁的线程
  - EVENTS_WAITS_SUMMARY_BY_INSTANCE 有两行,代表两个锁对象
  - EVENTS_WAITS_SUMMARY_BY_EVENT_NAME 有一行,代表这个锁的类
用图来表示就是
  PFS_wait_locker (T-A, M-1) ----------
                                      |
                                      v
                                 PFS_mutex (M-1)
                                 - m_wait_stat    ------------
                                      ^                      |
                                      |                      |
  PFS_wait_locker (T-B, M-1) ----------                      |
                                                             v
                                                        PFS_mutex_class (M)
                                                        - m_wait_stat
  PFS_wait_locker (T-C, M-2) ----------                      ^
                                      |                      |
                                      v                      |
                                 PFS_mutex (M-2)             |
                                 - m_wait_stat    ------------
                                      ^
                                      |
  PFS_wait_locker (T-D, M-2) ----------


            ||                        ||                     ||
            ||                        ||                     ||
            vv                        vv                     vv


  EVENTS_WAITS_CURRENT ..._SUMMARY_BY_INSTANCE ..._SUMMARY_BY_EVENT_NAME

接下来说一下其中on the fly模式,所谓on the fly就是无需停滞,监控的聚合函数不会受到代码执行的影响,这是十分必要的,因为监控的聚合结果也是需要实时的。
简单来说,就是写入线程执行所有的计算,读取线程直接获取结果。
一般来说这种模式是需要被避免的,因为writer需要一定的代价

HIGHER_LEVEL模式则相反,监控的聚合由读入者直接读取所有的被聚合的数据,也就是reader执行所有的计算,而writer不需代价

当然也有一个折中模式MIXED




0 0
原创粉丝点击