草庐IT

xtrabackup2版本和xtrabackup8版本对比

李努力ly 2023-03-28 原文
导语

在使用xtrabackup8版本对mysql8版本进行备份恢复搭建从库的时候,继续使用xtrabackup2版本的方式,从xtrabackup_binlog_info 文件中找到gtid信息,执行purge,尝试多次发现搭建失败,于是对xtrabackup2和xtrbackup8版本备份流程(依据官网)进行了简单的分析和测试。

 

1、xtrabackup2.4版本备份mysql5.7流程

(1)整体流程:

xtrabackup是物理备份,通过复制数据文件来进行备份的,在复制innodb数据文件的时候,会导致数据内部不一致,但是由于redo事务日志的存在(它包含对innodb数据修改的记录),当innodb启动的时候会检查数据文件和事务日志,该提交提交该回滚回滚,从而保证了一致性。

xtrabackup在启动的时候会记住日志序列号(LSN),然后复制数据文件,然而当数据量较大的时候,复制数据文件是需要一定的时间的,如果该时间内不断有写入业务的话,那么将会使数据库处于不同的时间点。这时xtrabackup会从后台启动一个事务日志监测进程(每秒检测一次),并不断的复制事务日志的修改,由于事务日志是循环的方式写的,所以在xtrabackup开始的时候就会不断的复制事务日志的修改。

将使用ftwrl加全局读锁,来备份非innodb表,并且写xtrabackup_binlog_info文件,使用FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS来刷盘redo log,阻止所有可能改变二进制日志位置或Exec_Master_Log_Pos或Exec_Gtid_Set的操作,然后停止redo log的复制操作,解锁二进制日志和表,然后写xtrabackup_info文件,备份完成。

(2)流程总结:

对于上述的备份过程整体简单总结一下就是:

①开始备份,连接数据库并进行权限校验以及确认版本(version_check Connected to MySQL server);

②备份innodb表,并开启后台线程拷贝redo log事务日志(>> log scanned up to (952373638).....);

③innodb表备份完成后,加ftwrl全局读锁来copy非innodb表文件,拷贝完成后(Finished backing up non-InnoDB tables and files)通过show master status写xtrabackup_binlog_info文件;

④将redo log buffer中的redo log进行刷盘(Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...);

⑤停止拷贝事务日志(Stopping log copying thread.);

⑥解锁二进制日志和表(Executing UNLOCK TABLES);

⑦写xtrabackup_info文件(Writing /data0/backup/9909/base/xtrabackup_info);

⑧备份完成。

(3)关于恢复后binlog信息位置点:

可以创建一个存储过程,来模拟数据的插入。

①首先进行一次全备份:

xtrabackup --defaults-file=/etc/mysql/9909.cnf --backup  --user=root --password=root --parallel=4  --ftwrl-wait-timeout=60 --ftwrl-wait-threshold=3 --rsync --socket=/tmp/mysql_9909.sock --target-dir=/data0/backup/9909/base

②进行prepare阶段:

xtrabackup --prepare --apply-log-only --target-dir=/data0/backup/9909/base/

③查看xtrabackup_binlog_info 文件binlog点位信息:

mysql-bin.000026   1251702      9c94ddb7-7397-11ec-a69f-fa37ddbb3200:1-38088

④用备份文件启动mysql,查看binlog点位信息:

mysql> show master stauts;9c94ddb7-7397-11ec-a69f-fa37ddbb3200:1-34381可以看到该点位比xtrabackup_binlog_info要差很多,查看原来实例的binlog找到该两个gtid信息位置:9c94ddb7-7397-11ec-a69f-fa37ddbb3200:38088此处是一个insert语句:

我们在恢复的库中进行查询看看有没有这条记录,可以看到有这条记录,并且下一条记录就没了(因为上面的存储过程是按顺序插入的):

所以说在9c94ddb7-7397-11ec-a69f-fa37ddbb3200:38088之前的记录都已经存在了,而show master status查询出来的要落后好多,如果使用该binlog点位搭建从库的话(不执行purge)会出问题的,比如会出现主键冲突等。

(4)原因:在备份的时候通过show master status读取binlog信息,因为开启了binlog日志,所以show master status读取的是show global variables查出来的gtid的信息,然后保存到了xtrabackup_binlog_info文件中。这里使用的是备份文件进行启动的实例,binlog从1号开始,所以需要读取这个表,所以查出来的show master status是通过这个表来获取的,而这个表在原库没有更新过,所以会比xtrabackup_binlog_info文件中的gtid要少。

(5)补充:

在恢复的时候,需要进行准备阶段,该阶段使用复制的事务日志文件对数据文件进行崩溃恢复,完成之后,数据库就可以恢复和使用了。备份的非innodb表和innodb表最终保持一致,因为在准备阶段,innodb的数据会前滚到备份完成的点,而不是回滚。这个时间点和ftwrl的时间点相匹配,所以mysiam和innodb数据是一致的。

 

 

2、xtrabackup8.0版本备份mysql8.0流程

(1)整体流程:

xtrabackup是物理备份,通过复制数据文件来进行备份的,在复制innodb数据文件的时候,会导致数据内部不一致,但是由于redo事务日志的存在(它包含对innodb数据修改的记录),当innodb启动的时候会检查数据文件和事务日志,该提交提交该回滚回滚,从而保证了一致性。

xtrabackup在启动的时候会记住日志序列号(LSN),然后复制数据文件,然而当数据量较大的时候,复制数据文件是需要一定的时间的,如果该时间内不断有写入业务的话,那么将会使数据库处于不同的时间点。这时xtrabackup会从后台启动一个事务日志监测进程(每秒检测一次),并不断的复制事务日志的修改,由于事务日志是循环的方式写的,所以在xtrabackup开始的时候就会不断的复制事务日志的修改。

xtrabackup8在备份mysql8版本的时候,使用备份锁来代替ftwrl(mysql8通过lock instance for backup语句获取一个实例级备份锁)。当只有innodb表时,xtrabackup将尽可能避免使用备份锁和ftwrl。xtrabackup从performance_schema.log_status来获取二进制日志的信息。在mysql8中如果xtrabackup使用--slave-info参数或者存在非innodb表的时候(除了系统表),仍然需要ftwrl进行加锁。当支持备份锁时,xtrabackup会先拷贝innodb数据,然后运行lock tables for backup再拷贝myisam表。

在此之后,使用FLUSH NO_WRITE_TO_BINLOG BINARY LOGS切换binlog,并读取log_status表,使用FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS来刷盘redo log,阻止所有可能改变二进制日志位置的操作,然后将完成redo日志文件的复制,并获取二进制日志信息。完成后,将解锁二进制日志和表。然后写xtrabackup_info文件,备份完成。

2)流程总结:对于上述的备份过程分两种情况简单总结一下就是:

a、只有innodb表:

①开始备份,连接数据库并进行权限校验以及确认版本(version_check Connected to MySQL server);

②备份innodb表,并开启后台线程拷贝redo log事务日志(>> log scanned up to (952373638).....);

③innodb表备份完成后,copy非innodb表文件,拷贝完成后(Finished backing up non-InnoDB tables and files)通过切换binlog(Executing FLUSH NO_WRITE_TO_BINLOG BINARY LOGS)并查询log_status表(Selecting LSN and binary log position from p_s.log_status);

④拷贝新的binlog(Copying /data0/mysql/8001_test/mysql-bin.000011 to /data0/backup/8001/base/mysql-bin.000011),写mysql-bin.index文件和xtrabackup_binlog_info文件;

④将redo log buffer中的redo log进行刷盘(Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...);

⑤停止拷贝事务日志(Stopping log copying thread.);

⑥解锁二进制日志和表(Executing UNLOCK TABLES);

⑦写xtrabackup_info文件(Writing /data0/backup/9909/base/xtrabackup_info);

⑧备份完成。

b、包含myisam表:

①开始备份,连接数据库并进行权限校验以及确认版本(version_check Connected to MySQL server);

②备份innodb表,并开启后台线程拷贝redo log事务日志(>> log scanned up to (952373638).....);

③innodb表备份完成后,加ftwrl全局读锁来copy非innodb表文件,拷贝完成后(Finished backing up non-InnoDB tables and files)通过切换binlog(Executing FLUSH NO_WRITE_TO_BINLOG BINARY LOGS)并查询log_status表(Selecting LSN and binary log position from p_s.log_status);

④拷贝新的binlog(Copying /data0/mysql/8001_test/mysql-bin.000011 to /data0/backup/8001/base/mysql-bin.000011),写mysql-bin.index文件和xtrabackup_binlog_info文件;将redo log buffer中的redo log进行刷盘(Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...);

⑤停止拷贝事务日志(Stopping log copying thread.);

⑥解锁二进制日志和表(Executing UNLOCK TABLES);

⑦写xtrabackup_info文件(Writing /data0/backup/9909/base/xtrabackup_info);

⑧备份完成。

其实只有innodb表和包含myisam表,xtrbackup8备份的时候差别在于包含myisam表的时候增加了ftwrl操作。

(3)performance_schema.log_status表简介:

该表是为在线备份工具来使用的,提供了日志的信息,当查询log_status表时,服务器阻塞日志记录和相关管理更改,时间足够填充表,然后释放资源。

该表通知在线备份工具应该复制到二进制日志的哪个点以及每个通道的中继日志的信息。还提供了单个存储引擎的相关信息,例如最近的日志序列号(LSN)和innodb存储引擎的最后一个检查点的LSN。注意该表不允许执行truncate table。

(4)lock instance for backup简介:

是一个实例级别的备份锁,允许在联机备份期间进行DML操作。执行该命令需要backup_admin权限,当从早期版本升级到mysql8.0版本时,该权限会自动授权具有reload权限的用户。该备份锁防止文件被创建、重命名或者删除(比如repair table、truncate table、optimizer table等),对于redo中没有记录的修改的操作也会被阻止。

(5)关于恢复后binlog信息位置点(只测试只有innodb表的时候)可以创建一个存储过程,来模拟数据的插入。

①首先进行一次全备份:xtrabackup8 --defaults-file=/etc/mysql/8001.cnf --backup  --user=root --password=root --parallel=4  --ftwrl-wait-timeout=60 --ftwrl-wait-threshold=3 --rsync --socket=/data0/mysql/8001_test/mysql_8001.sock --target-dir=/data0/backup/8001/base

②进行prepare阶段:

xtrabackup8 --prepare --apply-log-only --target-dir=/data0/backup/8001/base/

③查看xtrabackup_binlog_info 文件binlog点位信息:

mysql-bin.000027   1027 c8020369-d117-11ec-9049-fa37ddbb3200:1-96358

④用备份文件启动mysql,查看binlog点位信息:

mysql> show master stauts;c8020369-d117-11ec-9049-fa37ddbb3200:1-96359可以看到该点位比xtrabackup_binlog_info 文件binlog点位要大,到底哪个是准确的呢?来看一下binlog:

插入了一条数据,在用备份启动的mysql上查看是否存在该数据:

已经存在该数据了,如果当做从库的话,还是从xtrabackup_binlog_info该文件去查找binlog点位然后执行purge,那么搭建起来的从库会报错,比如主键冲突等,或者造成数据不一致。所以xtrabackup8备份mysql8之后show master status就是正确的binglog点位,不用再去执行purge。

⑤原因:

因为xtrabackup8中在备份过程中多了两个步骤:

第一:切换binlog;

第二:拷贝新的binlog,并写mysql-bin.index文件。当使用备份启动实例的时候,由于binlog存在,所以启动的时候从binlog去读取点位信息,并更新mysql.gtid_executed表。

看一下原库的p_s.log_status表:

由于一直有数据插入所以该表一直是更新的。再来看一下恢复库的p_s.log_status表:

由于没有数据写入,所以和恢复后show master status保持一致。

该表主要的作用就是,在备份过程中提供一致性点位,在查询该表之后会执行Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...来阻止可能改变二进制位置的操作。

 

3、补充

①xtrabackup_binlog_info 文件binlog点位信息:1027position对应的gtid是: c8020369-d117-11ec-9049-fa37ddbb3200:96358而实际上1027position对应的gtid是: c8020369-d117-11ec-9049-fa37ddbb3200:96359可见xtrabackup_binlog_info 中的并不准确。

②当包含myisam表的时候,使用xtrabackup8进行备份,因为会执行ftwrl所以最后xtrabackup_binlog_info和show master status均一致。

 

参考:

https://dev.mysql.com/doc/refman/8.0/en/performance-schema-log-status-table.html

https://docs.percona.com/percona-xtrabackup/8.0/how_xtrabackup_works.html

https://docs.percona.com/percona-xtrabackup/2.4/how_xtrabackup_works.html

有关xtrabackup2版本和xtrabackup8版本对比的更多相关文章

  1. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  2. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  3. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  4. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  5. ruby-on-rails - 如何在发布新的 Ruby 或 Rails 版本时收到通知? - 2

    有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:

  6. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  7. ruby-on-rails - 安装多个版本的 Rails 会覆盖以前的安装吗? - 2

    如果我一直输入geminstallrails使用不同版本的Rails会怎样?例如,我可以输入:geminstallrails--verson3.2.10或geminstallrails这给了我版本3.2.12。问题每次安装都会覆盖之前的吗?它会删除所有旧文件并添加我正在安装的新版本吗?或者如果我运行它两次,它会保留一些文件吗?我正在使用Ubuntu。 最佳答案 它将安装两个独立的gem。实际的可执行文件rails将调用最新版本。你可以覆盖它__例如,rails_3.2.10_将执行Rails3.2.10。bundler顺便说一下,如

  8. ruby - 在 Rails 项目中测试本地版本的 gem - 2

    我的Rails站点使用了一个确实不是很好的gem。每次我需要做一些新的事情时,我最终不得不花费与向实际Rails项目添加代码一样多的时间来为gem添加功能。但我不介意,我将我的Gemfile设置为指向我的gem的GitHub分支(我尝试提交PR,但维护者似乎已经下台)。问题是我真的没有找到一种合理的方法来测试我添加到gem的新东西。在railsc中测试它会特别好,但我能想到的唯一方法是a)更改~/.rvm/gems/.../foo。rb,这看起来不对或者b)升级版本,推送到Github,然后运行​​bundleup,这除了耗时之外显然是一场灾难,因为我不确定我所做的promise是否正

  9. ruby-on-rails - 不兼容的库版本 : nokogiri. bundle 需要 8.0.0 或更高版本,但 libiconv.2.dylib 提供 7.0.0 版本 - 2

    为了在我的mac上为一个rails项目安装mysql,我遵循了安装Homebrew软件和删除mac端口的在线建议。这是问题开始的地方。rails项目不会构建,我得到这个:[rake--prereqs]rakeaborted!dlopen(/Users/Parker/.rvm/gems/ruby-1.9.3-p448/gems/nokogiri-1.6.0/lib/nokogiri/nokogiri.bundle,9):Librarynotloaded:/opt/local/lib/libiconv.2.dylibReferencedfrom:/Users/Parker/.rvm/gem

  10. ruby - 我可以使用 RVM 为所有用户维护单一版本的 Ruby 吗? - 2

    我喜欢RVM。我意识到它的主要用例是让不同的用户在不同版本的Ruby之间切换。但是假设我正在将Rails应用程序部署到服务器,并且我只想运行单个版本的Ruby。特别是,我想要1.9.2,用RVM安装它很容易,但没有它就很痛苦。有没有一种方法可以让我说“我希望这是所有用户的规范Ruby安装”(连同它的所有gem),而不必手动创建一堆符号链接(symboliclink)并在每次更新到更新时更改它们Ruby版本? 最佳答案 以root身份安装RVM并执行sudorvmuse1.9.2--default。任何采购/usr/local/rvm

随机推荐