MySQL·答疑解惑·物理备份死锁分析

  

  背景   

  

  本文对5.6主备场景下,在备库做物理备份遇到死锁的情况下进行分析,希望对大家有所帮助。   

  

  这里用的的物理备份工具是Percona-XtraBackup (PXB),有的同学可能不清楚其备份流程,所以这里先简单说下,PXB的备份步骤是这样的:   

  
      <李>   拷贝InnoDB重做日志,这是一个单独的线程在拷,直到备份结束;   李   <李>   拷贝所有InnoDB ibd文件;   李   <李>   加全局读锁,执行刷新表与读锁(FTWRL);   李   <李>   见这种情况称之为拷贝纳、MYD多年并等文件;   李   <李>   获取位点信息,执行显示奴隶状态和显示主状态;   李   <李>   解锁,解锁表;   李   <李>   做一些收尾处理,备份结束。   李   
  

  如果MyISAM表很多话,全局读锁的持有时间会比较长,所以一般都在备库做备份。   

  

  另外冲表读锁这条命令会获取2个MDL锁,全局读锁(MDL_key::全球)和全局提交(MDL_key:提交)锁,MDL锁详情可以参考之前的月报MDL实现分析。   

  

  死锁分析   

  

  案例1   

  

  我们先看一下死锁时的现场是怎样的:   

  <>以前mysql>显示processlist;   + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - +   | | |用户Id主机| db | | | | |命令时间状态信息   + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - +   查询根|:| | | | | | | | init显示奴隶地位   | |系统用户| | |连接| |排队主事件到继电器| |   | |系统用户| | |连接| |等待提交锁| |   查询根|:| | | | | | | init显示processlist |   + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - +   

  可以看到显示奴隶状态被堵了很久,另外SQL线程在等待提交锁,说明在等待提交锁。   

  

  这时候如果我们再连接进去执行显示奴隶状态也会被堵,并且即使ctrl - c杀死掉线程,线程依然还在。   

  <>以前mysql>显示processlist;   + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - +   | | |用户Id主机| db | | | | |命令时间状态信息   + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - +   查询根|:| | | | | | | | init显示奴隶地位   | |系统用户| | |连接| |排队主事件到继电器| |   | |系统用户| | |连接| |等待提交锁| |   根|:| | | |死亡| | init | |显示奴隶地位   查询根|:| | | | | | | init显示processlist |   根|:| | | |死亡| | init | |显示奴隶地位   根|:| | | |死亡| | init | |显示奴隶地位   查询根|:| | | | | | | | init显示奴隶地位   + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - +   

  pstack看下相关线程的回溯,显示奴隶状态线程的回溯如下,非常明显是在等互斥锁,对应代码为,mysql_mutex_lock(和mi→扶轮领导学院(rli)→data_lock):   

  
 __lll_lock_wait _L_lock_974 __GI___pthread_mutex_lock inline_mysql_mutex_lock show_slave_status mysql_execute_command mysql_parse dispatch_command do_command do_handle_one_connection handle_one_connection…
  

  SQL线程的回溯如下,在等提交锁:   

  
 pthread_cond_timedwait inline_mysql_cond_timedwait MDL_wait: timed_wait MDL_context:: acquire_lock ha_commit_trans trans_commit Xid_log_event:: do_commit Xid_log_event:: do_apply_event Log_event:: apply_event apply_event_and_update_pos exec_relay_log_event handle_slave_sql…

MySQL·答疑解惑·物理备份死锁分析