最近在我们线上库物理备份的时候出现一个奇怪的现象:
我们备份都在从库上备份的,在业务低一般是在晚上2点钟开始备份.有天发现从库的延迟一直在增加,登录上实例,通过show processlist 发现,sql 线程在等待 binlog lock。同时看到我们从2点钟开始的压缩远程备份并没有完成,备份日志还在扫面ibd文件。
那么这个binlog lock 是谁持有的呢?仔细想想我们的业务场景,这是一个只读从库,且库上便没有提供任何读的服务,唯一的一个疑点就是我们的备份导致的,通过show processlist 可以看到,Time列的数值 均是18510,两个时间上边吻合,那么问题可以初步确认是由于备份引起的。
mysql> show processlist;
+---------+-------------+-----------+------------+---------+-------+-----------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+---------+-------------+-----------+------------+---------+-------+-----------------+
| 4613465 | system user | | NULL | Connect | 65348 | Waiting for master to send event | NULL | 0 | 0 |
| 4613466 | system user | | NULL | Connect | 18510 | Waiting for binlog lock | NULL | 0 | 0 |
| 4631056 | dbbackup | localhost | NULL | Sleep | 18510 | | NULL | 0 | 0 |
进一步的,我们去找找官文,看看什么时候xtrabackup 会用到这个binlog lock 呢?截取一段出来:
- LOCK TABLES FOR BACKUP
- ... copy .frm, MyISAM, CSV, etc. ...
- LOCK BINLOG FOR BACKUP
- UNLOCK TABLES
- ... get binlog coordinates ...
- ... wait for redo log copying to finish ...
- UNLOCK BINLOG
可以看到,Binlog Lock是在备份的尾声阶段,是为了在获取Master 或者slave 的一致性位置点而是用的。
那么问题来了, 我们的备份现在是到了那个阶段呢?如果已经到了尾声阶段,那么这个锁Binlog的过程应该是很短暂的。
为了确认我们当前备份的一个状态, 使用strace -p{pid} 来看一下,当前xtrabackup、innobackupex 都在做些什么事情。
在通过strace 查看这个进程到底在做什么事之前, 我们先来看看一些前埔的知识:
由于我们备份MySQL 是主要用到 innobackupex 和 xtrabackup,前者是一个 perl 脚本,后者是 C/C++ 编译的二进制。
xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互;而innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。简单来说,innobackupex 在 xtrabackup 之上做了一层封装。
一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行;另外一个原因是我们可能需要保存位点信息。
那么一个perl脚步和C程序是如何进行通信的呢?它们是如何知道撒时候该执行什么步骤的呢?
2个工具之间的交互和协调是通过控制文件的创建和删除来实现的,主要文件有:
xtrabackup_suspended_1
xtrabackup_suspended_2
xtrabackup_log_copied
来看一张图,了解一下innobackupex 和 xtrabackup 之间是如何协调的
举个栗子,我们来看备份时 xtrabackup_suspended_2 是怎么来协调2个工具进程的
- innobackupex 在启动 xtrabackup 进程后,会一直等 xtrabackup 备份完 InnoDB 文件,方式就是等待 xtrabackup_suspended_2 这个文件被创建出来;
- xtrabackup 在备完 InnoDB 数据后,就在指定目录下创建出这个文件,然后等这个文件被 innobackupex 删除;
- innobackupex 检测到文件 xtrabackup_suspended_2 被创建出来后,就继续往下走;
- innobackupex 在备份完非 InnoDB 表后,删除 xtrabackup_suspended_2 这个文件,这样就通知 xtrabackup 可以继续了,然后等 xtrabackup_log_copied 被创建;
- xtrabackup 检测到 xtrabackup_suspended_2 文件删除后,就可以继续往下了。
- 是不是感觉有点不可思议,通过文件是否存在来控制进程,这种方式非常的不靠谱,因为非常容易被外部干扰,比如文件被别人误删掉,或者2个正在跑的备份控制文件误放在同一个目录下,就等着备份乱掉吧,但是 Percona 就是这么干的。
---------------------------------------OK ,开启我们的debug 模式-----------------------------------------------------------------
有了一个大概的概念后,我们继续,用strace来瞅瞅我们这两个备份的进程都在干撒?为什么会长期持有binlog 锁不释放呢?
首先我们看一下 xtrabackup这个进程是在做什么:
/usr/bin/xtrabackup --defaults-file=/data/mysql/xxxx/my.cnf --defaults-group=mysqld --backup --suspend-at-end --target-dir=/tmp --innodb_data_file_path=ibdata1:12M:autoextend --tmpdir=/tmp --extra-lsndir=/
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=5, ...}) = 0
select(0, NULL, NULL, NULL, {0, 200000}
可以看到,我们的xtrabackup 当前是在判断 xtrabackup_suspended_2 这个文件的状态,因为我们拷贝完了ibd 文件。创建了 xtrabackup_suspended_2 这个文件,通知我们的innobackupex ,我的ibd 文件拷贝完成了,等待下一步的指令,也就是说等待这个文件被删除。
那么继续我们再看看innobackupex ,看看他又在做什么事情:
perl /usr/bin/innobackupex --ibbackup=/usr/bin/xtrabackup --defaults-file=/data/mysql/xxxxx/my.cnf --user=dbbackup --password=xxxxxx --slave-info --stream=tar /tmp
stat("/tmp/xtrabackup_log_copied", 0x7c6130) = -1 ENOENT (No such file or directory)
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0x7fff9aad0750) = 0
wait4(21337, 0x7fff9aad077c, WNOHANG, NULL) = 0
可以看到它在等待 xtrabackup_log_copied 文件被创建。
到此,我们可以看到,innobackupex 和xtrabackup 现在处于在两个不同的层级上了,innobackupex 已经超前了xtrabackup,认为当前的xtrackup 下一步应该创建文件告诉我redlog已经拷贝完成了。
那么到此,我们已经很明显的看到 这个备份已经乱掉了。
ok,既然问题已经弄明白了, 那么我们有什么应对策略呢?
1. 备份时间尽量错开,两个实例之间备份预留足够大的备份时间
2. 备份的临时目录指定到不同的地方,避免实例间备份互相干扰
3. 在2.3 版本以上 innobackupex 已经用C语言重写了innobackupex,升级到次版本即可解决
===================================================================================
附一个的xtrackup 备份过程堆栈日志(只保留通信间协调信息):
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
write(2, "xtrabackup: Creating suspend fil"..., 80) = 80
open("/tmp/xtrabackup_suspended_2", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0660) = 7
write(7, "1588", 4) = 4
close(7) = 0
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=4, ...}) = 0
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=4, ...}) = 0
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=4, ...}) = 0
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=4, ...}) = 0
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=4, ...}) = 0
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
stat("/tmp/xtrabackup_suspended_2", 0x7fffe0e0a970) = -1 ENOENT (No such file or directory)
pread(4, "\0\0\0\0\0\23\32\36\0\0\0\2\203o\215\223CY=\223\4\0\0\0\377\377\377\377\377\377\377\377"..., 4096, 4096) = 4096
pread(4, "\0\0\0\0\0\23\32\37\0\0\0\2\203o\217,CY?,\4\0\0\0\377\377\377\377\377\377\377\377"..., 4096, 12288) = 4096
pread(4, "\0\0\0\0\0\23\32\37\0\0\0\2\203o\217,CY?,\4\0\0\0\377\377\377\377\377\377\377\377"..., 4096, 12288) = 4096
write(2, "xtrabackup: The latest check poi"..., 68) = 68
futex(0x1bef89c, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x1bef860, 46) = 1
futex(0x1bef860, FUTEX_WAKE_PRIVATE, 1) = 1
write(2, "xtrabackup: Stopping log copying"..., 41) = 41
write(2, ".", 1) = 1
select(0, NULL, NULL, NULL, {0, 200000}) = 0 (Timeout)
write(2, "\n", 1) = 1
write(2, "xtrabackup: Creating suspend fil"..., 79) = 79
open("/tmp/xtrabackup_log_copied", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0660) = 7
write(7, "1588", 4) = 4
close(7) = 0
open("/tmp/xbtempjD8Ghu", O_RDWR|O_CREAT|O_EXCL, 0600) = 7
unlink("/tmp/xbtempjD8Ghu") = 0
write(7, "backup_type = full-backuped\nfrom"..., 97) = 97
fadvise64(7, 0, 0, POSIX_FADV_DONTNEED) = 0
open("/tmp/xtrabackup_checkpoints", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 8
fstat(8, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(8, "backup_type = full-backuped\nfrom"..., 97) = 97
close(8) = 0
write(1, "xtrabackup_logfile\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
===================================================================================
附innobackupex 备份间通信日志:
wait4(18608, 0x7fffa4d91c1c, WNOHANG, NULL) = 0
stat("/tmp/xtrabackup_suspended_2", 0x249f130) = -1 ENOENT (No such file or directory)
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0x7fffa4d91bf0) = 0
wait4(18608, 0x7fffa4d91c1c, WNOHANG, NULL) = 0
......................
stat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=5, ...}) = 0
write(2, "161101 10:25:56 innobackupex: E"..., 67) = 67
sendto(3, "\27\0\0\0\3LOCK BINLOG FOR BACKUP", 27, 0, NULL, 0) = 27
sendto(3, "\22\0\0\0\3SHOW SLAVE STATUS", 22, 0, NULL, 0) = 22
sendto(3, "\17\0\0\0\3SHOW VARIABLES", 19, 0, NULL, 0) = 19
open("/tmp/xtrabackup_slave_info", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4 = 0
lstat("/tmp/xtrabackup_slave_info", {st_mode=S_IFREG|0644, st_size=77, ...}) = 0
unlink("/tmp/xtrabackup_slave_info") = 0
sendto(3, "\23\0\0\0\3SHOW MASTER STATUS", 23, 0, NULL, 0) = 23
open("/tmp/xtrabackup_binlog_info", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
lstat("/tmp/xtrabackup_binlog_info", {st_mode=S_IFREG|0644, st_size=27, ...}) = 0
unlink("/tmp/xtrabackup_binlog_info") = 0
sendto(3, "%\0\0\0\3FLUSH NO_WRITE_TO_BINLOG EN"..., 41, 0, NULL, 0) = 41
lstat("/tmp/xtrabackup_suspended_2", {st_mode=S_IFREG|0640, st_size=5, ...}) = 0
unlink("/tmp/xtrabackup_suspended_2") = 0
stat("/tmp/xtrabackup_log_copied", 0x1ce5130) = -1 ENOENT (No such file or directory)
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, {0, 583650111}) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
restart_syscall(<... resuming interrupted call ...>) = 0
wait4(17273, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 17273
stat("/tmp/xtrabackup_log_copied", {st_mode=S_IFREG|0640, st_size=5, ...}) = 0
lstat("/tmp/xtrabackup_log_copied", {st_mode=S_IFREG|0640, st_size=5, ...}) = 0
unlink("/tmp/xtrabackup_log_copied") = 0
sendto(3, "\16\0\0\0\3UNLOCK BINLOG", 18, 0, NULL, 0) = 18
sendto(3, "\16\0\0\0\3UNLOCK TABLES", 18, 0, NULL, 0) = 18
recvfrom(3, "\7\0\0\1\0\0\0\2\0\0\0", 16384, 0, NULL, NULL) = 11
write(2, "161101 10:25:57 innobackupex: A"..., 51) = 51
lstat("/tmp/xtrabackup_pid", {st_mode=S_IFREG|0644, st_size=5, ...}) = 0
unlink("/tmp/xtrabackup_pid") = 0
stat("/data/mysql/3307//ib_buffer_pool", {st_mode=S_IFREG|0660, st_size=1244, ...}) = 0
write(2, "\ninnobackupex: Backup created in"..., 50) = 50
write(2, "innobackupex: MySQL binlog posit"..., 85) = 85
write(2, "innobackupex: MySQL slave binlog"..., 119) = 119
sendto(3, "\26\0\0\0\3SELECT UUID() AS uuid", 26, 0, NULL, 0) = 26
参考doc:
- MySQL 利用SQL线程对Binlog操作
背景: 对于MySQL的binlog的查看都是用其自带的工具mysqlbinlog进行操作的,其实还有另一个方法来操作binlog,就是Replication中的SQL线程去操作binlog,其实bi ...
- MySQL 利用SQL线程对Binlog操作(转)
背景: 对于MySQL的binlog的查看都是用其自带的工具mysqlbinlog进行操作的,其实还有另一个方法来操作binlog,就是Replication中的SQL线程去操作binlog,其实bi ...
- Slave SQL: Error 'Incorrect string value ... Error_code: 1366
背景: 主从环境一样,字符集是utf8. Slave复制报错,平时复制都正常也没有出现过问题,今天突然报错: :: :: :: :: Error_code: :: perror 1366 MySQL ...
- MySQL5.6 Waiting for Commit Lock
mysql Bug#19843808 自动修复记录 MySQL5.6和Xtrabackup之间存在一个bug,这个bug在5.6.23中已经修复. Xtrabackup备份的时候执行flushs t ...
- mysql故障(主从复制sql线程不运行)
故障现象: 进入slave服务器,运行: mysql> show slave status\G ....... Relay_Log_File: localhost Relay_Log_Pos: ...
- Java多线程:线程间通信之Lock
Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...
- MySQL DROP DB或TABLE场景下借助SQL Thread快速应用binlog恢复方案
[问题] 假设有这种场景,误操作DROP DB或TABLE,常规的恢复操作是还原全备份,并用mysqlbinlog追加到drop操作前的位置. 如果需要恢复的binlog的日志量比较大而我们只希望恢复 ...
- mysql主从架构,IO、SQL线程运行为YES,从库没有同步数据
mysql基于binlog主从复制架构,IO.SQL线程运行为YES,从库没有同步数据 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_D ...
- Ubuntu Linux处理Waiting for cache lock: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 3365 (unattended-upgr)问题
问题 在Ubuntu中,执行apt install后,出现以下问题: Waiting for cache lock: Could not get lock /var/lib/dpkg/lock-fro ...
随机推荐
- .net mvc中session的锁机制
今天遇到个奇怪的问题, 一个秒杀商品系统, 大量秒杀请求进来, 到了action居然是单线程执行! 这样产生的效果就是“这个系统好慢啊!!”. 可是我没有加lock,为什么会变成单线程执行呢? 找资料 ...
- Shader Variants 打包遇到的问题
1. 遇到的问题 最常见的是打包到手机后效果与PC上不一致,具体情况比如: 光照贴图失效 雾失效 透明或者cutoff失效 以上首先需要检查的地方是Shader变体的编译设置 2. 超级着色器编译成N ...
- [Processing]在画布上写文本
准备工作 这一步只是我强迫症犯了哈,这个随意,画几根线而已.每一小格10个像素,中格50,大格100像素 void setup() { size(,); } void draw() { backgro ...
- SQL Server上DBLINK的创建,其实很简单!(上)
今天给大家来分享一下跨服务器操作数据库,还是以SQL Server的管理工具(SSMS)为平台进行操作. 什么是跨服务器操作? 跨服务器操作就是可以在本地连接到远程服务器上的数据库,可以在对方的数据库 ...
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY4
2018/05/21 [生成器详解:廖雪峰的官方网站](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d ...
- JavaScript学习笔记(八)—— 补
第九章 最后的补充 一.Jquery简单阐述 JQuery是一个JavaScript库,旨在减少和简化处理DOM和添加视觉效果的JavaScript代码:使用时必须得添加库路径:学习路径:http:/ ...
- Netty源码分析第4章(pipeline)---->第3节: handler的删除
Netty源码分析第四章: pipeline 第三节: handler的删除 上一小节我们学习了添加handler的逻辑操作, 这一小节我们学习删除handler的相关逻辑 如果用户在业务逻辑中进行c ...
- maven项目的标准目录结构
maven项目的标准目录结构如下:
- 《The Mythical Man-Month(人月神话)》读后感(1)
临近考试周,这里我通过平时阅读的<人月神话>十九个章节和知乎.简书等网页中网友们对<人月神话>的读后感,对书中各个章节进行简单的总结,以下均为个人手打观点的思考与整合,仅供大家 ...
- vi/vim命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/mondol/p/vi-examples.html 进入vi vi filename # 打开或新建文件,并将光标置于第 ...