衡铁刚 1)2011-2013:Alibaba MySQL DBA 2)2014-至今: Alibaba 数据库PD
分类: Mysql/postgreSQL
2012-11-25 17:16:37
某业务DB紧急扩容,服务器空间快爆了,在MM结构不影响slave服务情况下,选择Innobackupex备份并恢复,一致性时间点在备份结束时,不像mysqldump在备份开始时,这样备份期间的binlog就可以删除,可用空间被严重压榨,备份工具和恢复工具都部署好了,但是在备份预估时间过后迟迟未见通知,结果查看log,备份已经超时退出了,随后产品DBA、PE、开发工作都delay,sorry 呜呜呜
innobackupex-1.5.1: Error: Connection to mysql child process (pid=31612) timedout. (Time limit of 900 seconds exceeded. You may adjust time limit by editingthe value of parameter "$mysql_response_timeout" in this script.) while waiting for reply to MySQL request: 'FLUSH TABLES WITH READ LOCK;' at /usr/bin/innobackupex-1.5.1 line 336.
第一眼FLUSH TABLES WITH READ LOCK和超时,怀疑是什么操作block了,查看实例上的session,的确有一个已运行3000s+的查询,第一时间重新备份,操作完之后总觉心有不甘,1000+实例备份环境这种情况迟早还会出现的,决心搞定它(google-manual-code)
1. 增大超时时间,可以修改mysql_response_timeout值 default 900s (不明确实例上查询方式,很难超时时间设置,时间增长会引起连锁反映)
2. --no-lock 可以在备份non-innodb和frm文件时不锁表,但是master和slave的pos信息就无法记录,因为write_binlog_info和write_slave_info函数只在mysql_lockall函数中调用,而mysql_lockal调用了flush tables with read lock (不适合生产环境)
3. --safe-slave-backup,除了备库上长查询外,包含insert和update的长transaction也有可能引发这个问题,虽然概率很低,加上safe-slave-backup后备份开始时每隔3s会通过SHOW STATUS LIKE "slave_open_temp_tables"\G来检查当前实例的临时表数量,数量为0则开始备份,否则在尝试100次(300s)超时后,stop slave sql_thread开始备份,session中仍存在临时表时备份是否会对备份集可用性产生影响,可以考虑将这个参数加入物理备份脚本中(还需要测试)
之前遇到问题都是搜来搜去才能找到具体函数,借此机会扫遍code,下次就可以直奔主题了
Innobackupex 工作流程
check_args()检查命令行参数
print_version()打印程序版本信息
设置option_ibbackup_binary 区分copy_back、apply_log、auto_detect不同情况
Init() 得到 mysql版本信息、检查ibbackup_version、创建备份路径、设置备份路径下相关文件的路径
根据命令行参数进入不同的函数
l copy_back() 拷贝数据和索引文件从备份目录到原始目录
n 生成backup目录及子目录下ibdata文件的列表
n 拷贝非innodb表
n 拷贝innodb表
n 拷贝ib_logfile
l apply_log() 应用log file到数据文件
n 启动option_ibbackup_binary设置的ibbackup子进程
n creating ib_logfile*
l backup()并记录XTRABACKUP_BINARY信息
n mysql_open() 启动管道链接的子进程连接mysql
n mysql_check() 检查连接mysql的子进程是否OK,发送一个虚拟查询,等待mysql_response_timeout超时退出
n mysql_close() 关闭连接mysql子进程
n start_ibbackup() 创建子进程运行ibbackup来备份innodb数据和索引
n 如果不是远程备份,不是stream模式,进入wait_for_ibbackup_suspend() 检查ibbackup子进程是否还活着
n mysql_open()
n 如果指定--safe-slave-backup 进入wait_for_safe_slave() ,通过每隔3s启停sql thread来不断检查实例上打开临时表数目是否为0
n mysql_check()
n 如果没有指定--no-lock,进入 mysql_lockall(),执行FLUSH TABLES WITH READ LOCK;
n backup_files() 拷贝除ibd外所有的文件
n mysql_unlockall() 执行UNLOCK TABLES
n 如果指定--safe-slave-backup START SLAVE SQL_THREAD
n mysql_close()
根据ibbackup_exit_code值成功或错误退出
看完code之后,心中仍有疑问,因为在实际观察看到超时时间在300s+,但mysql_response_timeout变量值是900s,百思不得其解