• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

MySQL备份恢复:Xtrabackup锁问题分析

MySQL 彭东稳 7年前 (2017-08-22) 34657次浏览 已收录 0个评论

XtraBackup的备份过程可以看出,XtraBackup可以实现Innodb表的无锁备份,但是一个数据库中,即使所有的业务表都是InnoDB表,但是还存在一些MySQL系统库下的user表等,均是myisam表(MySQL 8.0均替换为InnoDB),同时备份过程需要获取Binlog文件名和位置,也要保证表定义文件的一致性,所以从整个实例的角度,即使用XtraBackup还是有一段时间需要执行Flush table with read lock全局锁的,会对用户访问产生影响,同时由于Flush table with read lock的一些特殊性,如果稍不注意,可能会对用户访问数据库产生致命影响。

MySQL官网文档对Flush tables with read lock的解释:

Closes all open tables and locks all tables for all databases with a global read lock.

If the thread that is doing FLUSH TABLES has a lock on some tables, it will first close the locked tables, then wait until all other threads have also closed them, and then reopen them and get the locks. After this it will give other threads a chance to open the same tables.

从上面的这段话,我们可以得到下面结论:

1. Flush tables with read lock会上一个实例级别的全局锁,该锁与Lock tables互斥。如果一个会话中使用LOCK TABLES语句对某表加了表锁,在该表锁未释放前,那么另外一个会话如果执行FLUSH TABLES和FLUSH TABLES WITH READ LOCK语句会被阻塞,而如果数据库中lock_wait_timeout参数设置时间太短,innobackupex将会因为执行FLUSH TABLES WITH READ LOCK语句获取全局读锁超时而导致备份失败退出。

2. 如果一个会话正在执行DDL语句,那么另外一个会话如果执行FLUSH TABLES和FLUSH TABLES WITH READ LOCK语句会被阻塞,而如果数据库中lock_wait_timeout参数设置时间太短,innobackupex将会因为执行FLUSH TABLES WITH READ LOCK语句获取全局读锁超时而导致备份失败退出。

3. 如果一个会话正在执行DML大事务(DML语句正在执行,数据正在发生修改,而不是使用lock in share mode和for update语句来显式加锁),那么另外一个会话如果执行FLUSH TABLES和FLUSH TABLES WITH READ LOCK语句会被阻塞,而如果数据库中lock_wait_timeout参数设置时间太短,innobackupex将会因为执行FLUSH TABLES WITH READ LOCK语句获取全局读锁超时而导致备份失败退出。

4. 如果一个会话出现一个慢查询,也会造成另外一个会话如果执行FLUSH TABLES和FLUSH TABLES WITH READ LOCK语句会被阻塞。

可能大家认为Flush tables with read lock仅仅是一把读锁,即使阻塞了也不会影响正常的读,但是事实不是这个样子的。Peter Zaitsev 在文献【1】中提到了Flush tables with read lock的潜在风险。概括的讲,如果Flush table with read lock执行完毕,成功获取到了全局实例锁,后续的快照读和S锁的读是没有问题的,只是阻塞DDL、写;但是如果一旦因为表无法关闭或者因为其他的锁导致无法正常获取到表锁使得Flush table with read lock阻塞,这个后果将是灾难性的,所有的读,无论是快照读,还是S锁或者X锁的读,均会被阻塞,因为Flush table with read lock需要关闭表,这点是需要所有数据库运维人员警惕的,我们的数据库也因此导致了服务的长时间不可用。

另外如果你看过xtrackup备份时产生的SQL语句,你会看到lock_wait_timeout参数设置的有多大。

MySQL备份恢复:Xtrabackup锁问题分析

在执行FLUSH NO_WRITE_TO_BINLOG TABLES语句之前,有这样一句语句:SET SESSION lock_wait_timeout=31536000,备份时会在session级别把锁超时时间改了,so…除了加表锁忘记释放之外,其他两种情况估计不太可能碰到锁超时的情况!!当然,如果每天备份一次,那么我们不太可能让innobackupex在备份时,获取全局读锁时等待31536000秒。

XtraBackup从1.4到2.1.3均存在这样的隐患,在2.1.4的Release Notes中我们找到了相关描述:

Percona XtraBackup has introduced additional options to handle the locking during the FLUSH TABLES WITHREAD LOCK.These options can be used to minimize the amount of the time when MySQL operates in the read-only mode.

显然,Percona已经意识到了这个问题的严重性,提供了两种解决问题的思路,一是设置超时时间,二是kill其他阻塞线程。

1. 设置超时时间

XtraBackup设置一个超时时间,避免无限期的等待。Xtrabackup提供了一下参数实现该功能:

--lock-wait-timeout=SECONDS :一旦Flush table with read lock被阻塞超过预定时间,则XtraBackup出错返回退出,该值默认为0,也就是说一旦阻塞,立即返回失败。

--lock-wait-query-type=all|update :该参数允许用户指定,哪类的SQL语句是需要Flush table with read lock等待的,同时用户可以通过–lock-wait-threshold=SECONDS设置等待的时间,如果不在query-type指定的类型范围内或者超过了wait-threshold指定的时间,XtraBackup均返回错误。如果指定update类型,则UPDATE/ALTER/REPLACE /INSERT 均会等待,ALL表示所有的SQL语句。

2. kill其他阻塞线程

Kill掉所有阻塞Flush table with read lock的线程:

--kill-long-queries-timeout=SECONDS :参数允许用户指定了超过该阈值时间的查询会被Kill,同时也允许用户指定Kill SQL语句的类型。

--kill-long-query-type=all|select :默认值为ALL,如果选择Select,只有Select语句会被Kill,如果Flush table with read lock是被Update语句阻塞,则XtraBackup不会处理。

数据库运维人员在备份数据库时,应选择正确的XtraBackup版本规避该问题。同时,个人在使用XtraBackup在Slave做备份时,还碰到跟SQL线程产生死锁的情况。MariaDB并行复制,死锁信息如下:

xtrabackup提供了--safe-slave-backup选项,该选项表示为保证一致性复制状态,这个选项停止SQL线程并且等到show status中的slave_open_temp_tables为0的时候开始备份,如果没有打开临时表,备份会立刻开始,否则SQL线程启动或者关闭知道没有打开的临时表。如果slave_open_temp_tables在--safe-slave-backup-timeount(默认300秒)秒之后不为0,从库SQL线程会在备份完成的时候重启。

简而言之,该选项可以停止SQL线程,也就避免了备份死锁的问题,随暴力但也能解决问题,用不用自己看着办。

PS:很多人喜欢在备份前先flush binary logs一把,其实在有大事务对数据进行修改时,一不小心可能就会出现数据库hang死,所以不建议这么做。另外,innobackupex备份期间,在数据库中创建的连接不要误杀,否则备份失败。

<参考>

XtraBackup之踩过的坑

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

https://bugs.mysql.com/bug.php?id=70307

由FTWRL导致的MySQL从库死锁分析及参数深究

Percona Xtrabackup对FLUSH TABLES WITH READ LOCK改进


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (5)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!