背景
本文对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·答疑解惑·物理备份死锁分析