【Mysql】主机cpu之系统使用率过高

  <强>
     
  

  

     

     <强> InnoDB线程同步机制      

  我们知道linux线程同步有互斥锁,自旋锁,条件变量,rw锁等多种同步机制,InnoDB并没有直接使用系统的同步机制,而是自己定义了互斥结构数据结构kernel_mutex,将系统的自旋锁,互斥锁,和条件变量融合一起   

  【Mysql】主机cpu之系统使用率过高”> <br/>
  <p>
  
  </p>
  <ul类=   <李>   

  kernel_mutex主要涉及mutex_create、mutex_enter mutex_exit函数,会分别使用glibc的malloc()和free()调用动态分配和释放内存   

  李   <李>   

  封装互斥和条件变量,图中绿色框区域   MySQL线程之间发送异步信号来进行同步主要通过os_event_struct结构体中的os_mutex(封装操作系统的pthread_mutex_t)和cond_var(封装操作系统的pthread_cond_t)成员对象实现。当InnoDB在获取锁的时候,首先先努力自旋一段时间,如果超过innodb_sync_spin_loops的阈值,就会通过函数os_event_wait_low()在os_event_struct→cond_var上等待。如图,当某个线程释放了锁的时候,通过os_cond_broadcast尝试发送广播唤醒所有等待os_event_struct→cond_var条件变量的线程。这些线程被唤醒后又继续竞争争抢os_event_struct→os_mutex   

  李   <李>   

  自旋锁,图中黄色框区域   通过lock_word做旋转等待。线程想要争抢锁的时候先判断这个值,如果lock_word为1就继续自旋等待。如果发现其他线程释放了锁该值变为0的时候,就通过test_and_set改为1,“告诉”其他线程这把锁被持有了   

  李      

     

     <李>   

  kernel_mutex是个全局锁,保护事务,缓冲池,锁,等InnoDB存储引擎实现的大部分对象。当MySQL突然有大量访问,并发一旦非常高的时候,互斥冲突非常剧烈,此时临界区变得非常大,同时也会浪费cpu很多时间空转。所以这也解释了sys cpu大量消耗在自选空转中   

  李   <李>   

  并且并发高的时候会频繁调用malloc()申请内存,而glibc本身的malloc()本书频繁调用系统mutex_lock()和释放(),在多线程高并发场景下并且资源不足的场景下,也会造成系统各种互斥竞争严重。大量线程被挂起等待os  pthread_cond_broadcast广播被唤醒,随之而来的是大量的上下文切换   

  李      

  通过dstat看到此时cpu每秒有近20 w次的上下文切换,综上所述,系统cpu负载高主要以下:   

     <李>   

  (1)cpu内核自旋态,大量线程cpu在内核态自旋等待   

  李   <李>   

  (2)系统上下文切换,又分为:   

  李            <李>   

  自旋仍然失败的,最终进入操作系统等,调用pthread_cond_wait等待条件满足时被唤醒   

  李   <李>   

  malloc()频繁加减os互斥锁,且系统内存紧张   

  李         
           1.3 sar -Bpgscank/spgscand/s节点(-)   节点的cpu:节点大小:MB   节点:MB   节点的cpu:节点大小:MB   节点:MB   节点的距离:   节点,,,:,,:,之前   

  虽然内存整体自由没有用的光,但是在numa默认的内存分配机制下,内存使用严重不均,node0还十分充足,但是node1几乎用光
  
  还可以使用strace来诊断!   

  

  https://huoding.com/2015/10/16/474   

  

  
  

  

【Mysql】主机cpu之系统使用率过高