背景介绍
在使用xtrabackup愉快的进行备份的同时,xtrabackup中由于锁带来的线上问题也是很令人头疼的~,所以就找个时间对xtrabackup中的三把锁以及遇见的线上问题进行简单梳理。
原理解析
- 第一步 :
LOCK TABLES FOR BACKUP
第一步:锁表,这一步发生在innoDB表[即事务类的表]备份完成后,非事务表备份之前;其次,这里加的是
MDL锁,影响非事务类表的写操作以及所有表的DDL操作,但是对事物类的表读写操作是不做限制的。
- 第二步 :
LOCK BINLOG FOR BACKUP
锁住binlog发生在所有的非事务表拷贝完成后,这一步也是由
MDL锁实现的。这一过程中锁住binlog,防止新的事物提交,保证redo log和binlog的一致性,redo log后续用来做崩溃恢复。
- 第三步 :
UNLOCK BINLOG
最后拷贝完成,释放资源。
备份日志中顺序如下:
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
本文的核心不是讲解备份的原理,备份的过程参考上图,详细过程参考 —— [ 官方文档 ]
在这个备份过程中思考几个问题,考考自己
Q1:xtrabackup拷贝到哪一个时间点?
—– 锁住binlog的那个时间点。
Q2:为什么要锁住binlog?
—– 锁binlog是为了获取当前binlog的位置吗?严格来讲并不是,主要是为了防止新的事物提交。这样保证了获取的redo log有commit log的事物是可以提交的,没有commit log的事物就是不用提交的。避免在崩溃恢复阶段,需要借助binlog信息来判断事物是提交还是回滚。
Q3:备份完成后redo的位点是和binlog一样还是比binlog多一些?如果多一些,那么如何确定需要应用有哪些?
—redo log会多一些,这也就是锁住binlog的意义所在。锁住了binlog保证了copy的redo log该提交的都有commit log的信息,多出来的redo log是没有commit log的信息的,最后在回放的过程中回滚就行。
Q4:锁住binlog和不锁binlog的区别?
— 都可以拿到binlog位点,锁了保证不会有新的事物提交,不用借助binlog去对比redo位置进行恢复,可以直接依靠redo的commit log信息进行恢复。
案例研究
案例1:mysql5.7开启并行复制 + slave_preserve_commit_order=1 +备份锁 > 死锁
| 2017-12-15 09:55:28 | 297524 | system user | Connect | 10047 | Waiting for backup lock | insert into myisam table |
| 2017-12-15 09:55:28 | 297525 | system user | Connect | 10047 | Waiting for preceding transaction to commit | |
| 2017-12-15 09:55:28 | 2006785 | backup | Query | 9440 | Waiting for binlog lock | LOCK BINLOG FOR BACKUP |
| 2017-12-15 09:55:28 | 297523 | system user | Connect | 10047 | Waiting for dependent transaction to commit |
从上面核心的processlist信息来看,Coordinator线程处于Waiting for dependent transaction to commit,有1个work线程处于Waiting for preceding transaction to commit(While the slave thread is waiting for other workers to commit their transactions it reports its status as Waiting for preceding transaction to commit)等待其他work线程commit,此时有个worker线程在执行insert into 非InnoDB表,等待Waiting for backup lock,这里的备份锁就是上面的第二步,而此时backup等待Waiting for binlog lock。
出现Waiting for dependent transaction to commit的原因是当slave_preserve_commit_order=1时,需要保证binlog顺序一样,后一个sequence_number提交的时候,会等待前一个sequence_number完成。Waiting for preceding transaction to commit。按照时间梳理就是:首先备份完了所有的InnoDB表,备份线程接着锁住了所有非InnoDB表;同时因为开启了并行复制,有两个线程并行执行SQL,297525执行完成等297524,为了保证binlog中的提交顺序;297524执行insert操作,等带backup线程释放table lock;backup线程等待297525释放binlog的ix锁;297525等待297524循环死锁;减少非InnoDB表可以降低死锁的概率
本文介绍了xtrabackup在MySQL备份过程中涉及的三把锁,包括锁表、锁binlog和资源释放,强调了锁binlog在保持redo log与binlog一致性中的作用。此外,通过案例分析了在开启并行复制和特定配置下可能出现的死锁问题。
1083

被折叠的 条评论
为什么被折叠?



