iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >mysqldump一致性热备的原理是什么
  • 728
分享到

mysqldump一致性热备的原理是什么

2024-04-02 19:04:59 728人浏览 独家记忆
摘要

Mysqldump一致性热备的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。首先用mysqldump执行一次一致性备份:$ 

Mysqldump一致性热备的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

首先用mysqldump执行一次一致性备份:

$ mysqldump -uroot -p --skip-opt --default-character-set=utf8  --single-transaction --master-data=2 --no-autocommit -B d1> backup.sql

关键参数解释:

  •  --single-transaction:执行一致性备份。

  •  --master-data=2:要求dump结果中以注释形式保存备份时的binlog位置信息。

  •  -B:指定要dump的数据库,在这里d1是一个使用InnoDB作为存储引擎的库,其中只有一个表t1。

执行完成后可以得到mysqld生成的general log,里面记录了mysqldump在备份过程中传给server的指令。

mysqldump一致性热备的原理是什么

其中关键的步骤我用框框作了标记,具体的解释请看下文。

mysqldump一致性备份的主要执行流程

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2.  连接server

  3.  两次关闭所有表,第二次关表同时加读

  4.  设置隔离级别为“可重复读”,开始事务并创建快照

  5.  获取当前binlog位置

  6.  解锁所有表

  7.  对指定的库与表进行dump

下面结合SQL内容与源码对以上主要步骤进行依次介绍。

流程剖析

1. 连接server

mysqldump首先与server建立连接,并初始化session,set一些session级的变量,对应SQL如下图

mysqldump一致性热备的原理是什么

其在main函数中对应的源码就是一个对connect_to_db函数的调用:

if (connect_to_db(current_host, current_user, opt_passWord)) {    free_resources();    exit(EX_MYSQLERR);

2. 两次关闭所有表,第二次关表同时加读锁

连接建立后,mysqldump紧接着执行两次关表操作,并在第二次关表同时给所有表加上读锁,对应SQL如下图:

mysqldump一致性热备的原理是什么

这一部分在main函数中对应的源码为:

if ((opt_lock_all_tables || opt_master_data ||       (opt_single_transaction && flush_logs)) &&      do_flush_tables_read_lock(mysql))    Goto err;

可以看到实际操作由do_flush_tables_read_lock函数进行,但是这里需要注意操作执行的前提条件,观察代码我们可以知道,这个关表操作只会在三种情况下进行:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2.  通过--lock-all-tables选项显式要求给所有表加锁。

  3.  通过--master-data选项要求dump出来的结果中包含binlog位置。

  4.  通过--single-transaction指定了进行单事务的一致性备份,同时通过--flush-logs要求刷新log文件。

看到这里不难知道,除了第一种情况显式要求加锁之外,情况3要求刷新log前没有其他事务在进行写操作,自然要对所有表加上读锁。情况2要求dump结果中准确记录dump进行时刻的binlog位置,为了准确地得到当前binlog的位置,自然就需要给所有的表加共享锁,防止其他并行事务进行写操作导致binlog更新,因此这里才有一个关表、加读锁的动作。

这里有一个细节,我们知道--single-transaction选项可以执行一致性备份,那么在只有--single-transaction选项时为什么不需要进行关表与加读锁的动作呢?这是因为--single-transaction所保证的一致性备份依赖于支持事务的存储引擎(如InnoDB),在后面会提到,mysqldump通过执行START TRANSACTION WITH CONSISTENT SNAPSHOT会创建一个数据库当前的快照与一个事务id,所有在该事务之后的事务所进行的数据更新都会被过滤,以此来保证备份的一致性。这种方式的优势在于不会在进行一致性备份时干扰其他事务的正常进行,实现了所谓的“热备”,但是缺点在于其依赖事务型存储引擎,对于使用MyISAM等不支持事务的存储引擎的表,--single-transaction无法保证它们的数据一致性。

接着查看do_flush_tables_read_lock函数的源码:

static int do_flush_tables_read_lock(MYSQL *mysql_con) {   return (mysql_query_with_error_report(               mysql_con, 0,              ((opt_master_data != 0) ? "FLUSH  TABLES"                                      : "FLUSH TABLES")) ||           mysql_query_with_error_report(mysql_con, 0,                                         "FLUSH TABLES WITH READ LOCK"));  }

可以看到逻辑比较简单,就是向server传入执行两个query,依先后次序分别时FLUSH TABLES和FLUSH TABLES WITH READ LOCK,这里核心的动作在于后面一个query,之所以需要前面的FLUSH TABLES是基于性能的考量,以尽可能减少加锁对其他事务的影响。

3. 设置隔离级别为“可重复读”,开始事务并创建快照

关表操作执行完后,mysqldump接着开启一个新事务并创建快照,对应SQL如下图:

mysqldump一致性热备的原理是什么

这一部分在main函数中对应的源码为:

if (opt_single_transaction && start_transaction(mysql)) goto err;

可以看到,只有在指定--single-transaction选项时这一步骤才会执行。实际上这一步就是mysqldump实现一致性热备的基础,我们接着查看start_transaction函数的源码:

static int start_transaction(MYSQL *mysql_con) {   // 省略部分非关键代码与注释   return (       mysql_query_with_error_report(mysql_con, 0,                                     "SET SESSION TRANSACTION ISOLATION "                                     "LEVEL REPEATABLE READ") ||       mysql_query_with_error_report(mysql_con, 0,                                     "START TRANSACTION "                                     ""));  }

可以看到核心动作是传给server执行的两个query,先是SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ确保当前会话的隔离级别是“可重复读”,然后通过START TRANSACTION 来开始一个新事务,产生一个新事务id,同时创建一个快照,dump过程中所使用的数据都基于这个快照。这样,所有在该事务之后的事务所进行的数据更新都会被过滤,备份的数据一致性因此得以保证。

但是,这样的热备方法,依赖于像InnoDB这样支持事务的存储引擎。相反,如MyISAM这种不支持事务的存储引擎在备份过程中的数据一致性则不能被保证。

4. 获取当前binlog位置

随后mysqldump执行一个SHOW MASTER STATUS的query,以获取当前binlog的位置信息:

mysqldump一致性热备的原理是什么

查看main函数中对应部分的源码可以看到,只有在指定--master-data选项时才会去获取、记录当前的binlog位置:

if (opt_master_data && do_show_master_status(mysql)) goto err;

查看do_show_master_status函数的实现,可以看到核心动作就是向server传入执行一个SHOW MASTER STATUS的query,最后将得到的binlog位置信息写入dump结果中。

static int do_show_master_status(MYSQL *mysql_con) {    MYSQL_ROW row;    MYSQL_RES *master;    const char *comment_prefix =        (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";    if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS")) {      return 1;    } else {      row = mysql_fetch_row(master);      if (row && row[0] && row[1]) {        print_comment(md_result_file, 0,                      "\n--\n-- Position to start replication or point-in-time "                      "recovery from\n--\n\n");        // 写入dump结果        fprintf(md_result_file,                "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",                comment_prefix, row[0], row[1]);        check_io(md_result_file);      }      // ...    }    return 0;  }

5. 解锁所有表

在正式开始dump操作之前,mysqldump会把前面操作中可能加了锁的表全部解锁:

mysqldump一致性热备的原理是什么

查看main函数中对应部分代码:

if (opt_single_transaction &&      do_unlock_tables(mysql))     goto err;

可以看到,只有在指定了--single-transaction选项时才会解锁所有先前被加锁的表,结合前面的思考可以推断,--single-transaction下所进行的备份通过事务性质可以保证数据的一致性,没有必要再保留对所有表所加的锁,因此这里执行解锁,以免阻塞其他事务的进行。

6. 对指定的库与表进行dump

前面的准备操作进行完成后,mysqldump开始正式进行选定库、表的dump操作:

mysqldump一致性热备的原理是什么

对指定数据库的实际dump由dump_databases函数执行(当指定了--all-databases要求dump所有库时,则由dump_all_databases函数执行)。

查看dump_databases函数的实现:

static int dump_databases(char **db_names) {    int result = 0;    char **db;    DBUG_TRACE;    for (db = db_names; *db; db++) {      if (is_infoschema_db(*db))        die(EX_USAGE, "Dumping \'%s\' DB content is not supported", *db);      if (dump_all_tables_in_db(*db)) result = 1;    }    if (!result && seen_views) {      for (db = db_names; *db; db++) {        if (dump_all_views_in_db(*db)) result = 1;      }    }    return result;  } 

逻辑比较清晰,先dump每个指定的数据库中所有的表,之后如果存在视图,则将对应视图也进行dump。我们的考察重点放在对表的dump上。

实际dump一个表的操作逻辑也比较清晰,就是先获取表的结构信息,得到表的创建语句,然后获取表中每行的实际数据并生成对应的insert语句。

不过,前面的general log中有个值得注意的点是SAVEPOINT的出现,这一点在MySQL 5.5的mysqldump中是没有的,查看dump_all_tables_in_db函数的实现,可以找到设置savepoint的对应代码:

// 创建savepoint   if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) {     verbose_msg("-- Setting savepoint...\n");     if (mysql_query_with_error_report(mysql, 0, "SAVEPOINT sp")) return 1;   }   while ((table = getTableName(0))) {     char *end = my_stpcpy(afterdot, table);     if (include_table(hash_key, end - hash_key)) {      dump_table(table, database); // 对表进行dump       // 省略部分代码...       // ROLLBACK操作             if (opt_single_transaction && mysql_get_server_version(mysql) >= 50500) {         verbose_msg("-- Rolling back to savepoint sp...\n");         if (mysql_query_with_error_report(mysql, 0, "ROLLBACK TO SAVEPOINT sp"))           maybe_exit(EX_MYSQLERR);       }

可以看到创建savepoint是在dump表之前,之后遍历库中的每个表,每当dump完一个表之后,便执行一次ROLLBACK TO SAVEPOINT sp操作,为什么呢?其实上面代码的注释已经解释清楚了:

简单来说,当我们dump完一个表后后面都不再需要使用这个表,这时其他事务的DDL操作不会影响我们dump得到数据的正确性,增加savepoint的意义在于,假如我们要dump表A,savepoint记录了dump表A之前尚未给表A加MDL锁的状态,当开始dump表A时,由于要进行一系列select操作,会给表A加上MDL锁防止其他事务的DDL操作改变表结构导致读动作出错;最后当对表A的dump完成后,后续都不会再访问表A了,此时没有释放的MDL锁没有意义,反而会阻塞其他并行事务对表A的DDL操作。

对此,MySQL的解决方法是在访问表A前通过SAVEPOINT sp记录一个savepoint,在dump完表A之后通过ROLLBACK TO SAVEPOINT sp回到当时的状态,即可释放对表A加的MDL锁,放行其他事务对该表的DDL操作。

小结

以上是mysqldump基于MySQL 8.0的一致性备份原理介绍,相比MySQL 5.5,现如今MySQL 8.0在mysqldump的实现存在一定改进,除了上面提到的savepoint机制是一个显著区别之外,还有诸如对GTID的支持、对column statistics的dump操作在本文中没有提及,但总体而言,mysqldump在一致性备份上的实现原理并没有多少改变。

拓展阅读——Percona的实现

MySQL从出现到普及,中途也出现了其他不少优秀的发行版,MySQL中一致性备份的实现其实也并不完美,因此如果能够考量其他发行版在这方面上的实现,也是一件有意义的事情。

Backup Lock

在前面我有提到,mysqldump中--single-transaction选项所实现的一致性备份不需要对表加锁,但这一特性基于事务型的存储引擎,因此只对InnoDB表或使用其他事务型存储引擎类型的表能够保证备份时过滤掉其他并行事务的更新操作;但对使用了MyISAM这种不支持事务的存储引擎的表,--single-transaction无法保证其数据的一致性,即若备份过程中出现了来自其他并行事务的更新操作,其很有可能被写入了备份中。

既然如此,若想对MyISAM的表进行备份,又想保证其一致性该怎么办?一种方式可以是在执行mysqldump时传入--lock-all-tables选项,这个选项会使得dump操作进行之前执行一个FLUSH TABLES WITH READ LOCK语句,并保证在dump的全程保持对所有表的读锁。但是无疑这是一种overkill,仅仅是为了保证一部分非事务型存储引擎的表的一致性,就需要对所有表加锁,进而业务上所有对server的写操作被阻塞一段时间(若备份的数据量大,这简直会造成一场灾难)。

这一问题,我尚未在MySQL 8.0中找到相应的好的解决方式,不过Percona对此给出了一个方案:在Percona发行版的mysqldump中,执行时可以传入一个--lock-for-backup选项,这个选项会使得mysqldump在dump之前,执行一个LOCK TABLES FOR BACKUP语句,这是一个Percona独有的query,其主要做以下几件事情:

  •  阻塞对MyISAM, MEMORY, CSV, ARCHive表的更新操作;

  •  阻塞对任何表的DDL操作;

  •  不阻塞对临时表与log表的更新操作。

显然,有了以上的特性,当同时传入--lock-for-backup与--single-transaction两个选项同时,mysqldump可以保证所有表的数据一致性,并且尽可能保证造成最少的线上业务干扰。

这一部分逻辑可以在Percona Server 8.0中mysqldump的代码中找到,在main函数中:

if (opt_lock_all_tables ||      (opt_master_data &&       (!has_consistent_binlog_pos || !has_consistent_gtid_executed)) ||      (opt_single_transaction && flush_logs)) {    if (do_flush_tables_read_lock(mysql)) goto err;    ftwrl_done = true;  } else if (opt_lock_for_backup && do_lock_tables_for_backup(mysql))    goto err;

细心的朋友会发现,这是对上面的“关表加读锁操作”进行的逻辑改写,其增加了一个else if逻辑分支,取代了之前的FLUSH TABLES; FLUSH TABLES WITH READ LOCK;操作,主要目的是为了与--single-transaction进行的一致性备份更好地兼容,实现对线上业务尽可能少的阻塞。

接着查看do_lock_tables_for_backup函数的实现,可以看到就是简单地向server传入一个Percona独有的LOCK TABLES FOR BACKUP语句:

static int do_lock_tables_for_backup(MYSQL *mysql_con) noexcept {    return mysql_query_with_error_report(mysql_con, 0, "LOCK TABLES FOR BACKUP");  }

Binlog Snapshot

在MySQL 8.0的实现中,有一个常用的选项,仍然会导致“讨人厌”的FLUSH TABLES WITH READ LOCK的执行,即--master-data选项。

前面提到,--master-data选项要求在dump之后的结果中存有当前备份开始时的binlog位置,为了满足所获得binlog位置的一致性,需要在执行SHOW MASTER STATUS前,获取对所有表的读锁以阻塞所有binlog的提交事件,因此要求执行一次FLUSH TABLES WITH READ LOCK。但是有没有更好的方式?Percona同样给出了自己的解决方法。

在Percona Server中,新增了两个全局status:Binlog_snapshot_file和Binlog_snapshot_pos,分别用来记录当前的binlog文件与binlog位置,通过SHOW STATUS LIKE 'binlog_snapshot_%'即可获取两个status的值。那么使用这个方式,跟SHOW MASTER STATUS有什么区别?

二者的区别在于,Binlog_snapshot_file和Binlog_snapshot_pos这两个status具有事务性,只要在执行SHOW STATUS LIKE 'binlog_snapshot_%'这个语句之前通过START TRANSACTION WITH CONSISTENT SNAPSHOT创建了新事务与一致性快照,Binlog_snapshot_file和Binlog_snapshot_pos所记录的则正是该事务开始时的binlog文件与位置信息,进而binlog信息的一致性得到保证,而这一过程的全程都不需要FLUSH TABLES WITH READ LOCK的执行。

相对的,SHOW MASTER STATUS是不具备事务性的,每次执行该语句返回的都是当前最新的binlog位置信息,这也是为什么执行它之前需要对所有表上读锁。

看完上述内容,你们掌握mysqldump一致性热备的原理是什么的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网数据库频道,感谢各位的阅读!

您可能感兴趣的文档:

--结束END--

本文标题: mysqldump一致性热备的原理是什么

本文链接: https://www.lsjlt.com/news/57834.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • mysqldump一致性热备的原理是什么
    mysqldump一致性热备的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。首先用mysqldump执行一次一致性备份:$ ...
    99+
    2024-04-02
  • 一致性读实现原理是什么
    本篇内容主要讲解“一致性读实现原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“一致性读实现原理是什么”吧!MySQL中的事务事务在RDBMS系统中概念基...
    99+
    2024-04-02
  • 什么是数据库的读一致性和写一致性
    一、读一致性 读一致性是指在数据库中的并发读操作中,读取到的数据应该是一致的。具体来说,当一个事务在执行读取操作时,如果另一个事务正在对同一数据进行修改(写操作),那么读取操作应该获取到已经提交的最新版本的数据,而不是读取到部分修改完成的数...
    99+
    2023-10-29
    数据库 读一致性 写一致性
  • TiDB用什么保证备份的一致性
    TiDB用什么保证备份的一致性,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。背景作为一名MySQL DBA,就应该了解MySQL备份无论是...
    99+
    2024-04-02
  • Webpack热更新的原理是什么
    本篇内容介绍了“Webpack热更新的原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、是什么H...
    99+
    2024-04-02
  • tomcat热部署的原理是什么
    Tomcat热部署的原理是使用了Servlet规范中的"Reload"功能。当Tomcat启动时,它会监视web应用程序的文件夹,比...
    99+
    2023-10-23
    tomcat
  • 什么是Cassandra的一致性级别
    Cassandra的一致性级别是指在对数据库进行读写操作时,系统保证数据的一致性的程度。Cassandra提供了三种一致性级别: ...
    99+
    2024-03-06
    Cassandra
  • tomcat热部署原理是什么
    Tomcat热部署是指在不停止Tomcat服务器的情况下,实时更新或添加新的Java类和资源文件。其原理主要包括以下几个步骤:1. ...
    99+
    2023-09-15
    tomcat
  • 什么是Java一致性Hash算法
    这篇文章主要介绍“什么是Java一致性Hash算法”,在日常操作中,相信很多人在什么是Java一致性Hash算法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是Java一...
    99+
    2024-04-02
  • Oracle备份恢复中热备份恢复及异机恢复的原理是什么
    Oracle备份恢复中热备份恢复及异机恢复的原理是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Oracle备份恢复之热备份恢复及异机...
    99+
    2024-04-02
  • Oracle读写一致性的概念是什么
    Oracle读写一致性是指在数据库系统中,当一个事务对数据进行更新后,其他事务在读取该数据时能够看到该更新后的最新值,而不会看到部分...
    99+
    2024-04-19
    Oracle
  • redis的一致性hash和hash槽是什么
    这篇文章主要讲解了“redis的一致性hash和hash槽是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“redis的一致性hash和hash槽是什么”...
    99+
    2024-04-02
  • MySQL备份的原理是什么
    这篇文章给大家介绍MySQL备份的原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。冷备份最简单的备份方式就是,关闭MySQL服务器,然后将data目录下面的所有文件进行拷贝保存...
    99+
    2024-04-02
  • MySQL半一致性读原理的示例分析
    小编给大家分享一下MySQL半一致性读原理的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! 1、什么是半一致性读A t...
    99+
    2024-04-02
  • python中实现热力图的原理是什么
    python中实现热力图的原理是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学...
    99+
    2023-06-14
  • Cassandra中一致性级别的作用是什么
    Cassandra中一致性级别指的是在数据写入或读取时,系统如何保证数据的一致性。一致性级别的作用是控制数据的可靠性和性能之间的权衡...
    99+
    2024-04-02
  • MySQL是怎么保证主备一致的
    目录MySQL 主备的基本原理binlog 的三种格式对比为什么会有 mixed 格式的 binlog?循环复制问题总结:抛出问题:大家知道 binlog 可以用来归档,也可以用来做...
    99+
    2024-04-02
  • MySQL怎么保证备份数据的一致性
    这篇文章主要讲解了“MySQL怎么保证备份数据的一致性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL怎么保证备份数据的一致性”吧!前言为了数据安全,数据库需要定期备份,这个大家都懂...
    99+
    2023-06-30
  • NoSQL中最终一致性指的是什么意思
    NoSQL中的最终一致性指的是系统中的所有副本最终会达到一致的状态,但在更新数据时可能会出现短暂的不一致性。在最终一致性模型中,系统...
    99+
    2024-05-07
    NoSQL
  • mysql双机热备的作用是什么
    MySQL双机热备的作用主要有以下几点: 提高系统的可用性:通过MySQL双机热备,可以保证系统在一台机器发生故障时,另一台机器...
    99+
    2024-04-09
    mysql
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作