背景
MySQL全量逻辑备份恢复最基础的方法,就是mysqldump生成文本,再通过source 命令直接导入。一般用于实例迁移或者版本升级。
这里说明最近碰到的一个失败例子。
描述
这个例子可以简要复现如下,在源库上执行如下操作:
use mydb;
create table t1 (id int);
create view v1 as select * from t1;
drop table t1;
之后执行 mysqldump mydb,发现mysqldump中途退出。简化后出错原因很明显,就是视图v1对应的表t1已经不存在,这个视图本身非法。
这个错误很危险,因为如果没有捕获这个错误,直接认为mysqldump执行完成,并将生成的结果应用于目标库,则会导致数据丢失!
其实这个问题并不像看起来那么简单。
一个问题
mysqldump只需要生成show create view v1的结果即可----这会导致在目标库source的时候报错----为什么会在dump的时候就报错?
MySQL Tips: mysqldump导出整库,默认情况下,会在导出前对整库里面的每个表加读锁,即Lock tables tb1 read, tb2 read,..., tbn read.
本例中由于视图v1需要的实体表t1已经不存在,lock table v1 read 返回失败。因此整个库所有表都没有正常导出。如果以此输出结果导入到目标库,则整库数据丢失。
MySQL Tips: mysqldump若正常结束,生成的文件结果最后一行是“-- Dump completed on + 时间”。
使用dump的结果文件必须先检查结果文件的完整性,判断末行的文本是一个推荐操作。
导整库的时候为什么需要对所有表都加读锁呢?目的是为了得到一致性读视图。也就是说,在导出整库期间,不会有更新,这样才保证导出数据的一致性。
而实际上这个是历史遗留问题,InnoDB本身支持一致性读,也就是说只要启动一个事务(begin/start transaction),则在此事务存续期间,对于本实例内InnoDB表的更新,此导出事务均不可见。也就是说InnoDB事务可以保证事务期间看到的视图与事务启动瞬间看到的一致。
而锁表会堵住更新,导库又往往是长时间的操作,因此备份期间能允许读写对OLTP应用来说至关重要。
MySQL Tips: 若确保mysqldump导出的数据中只有InnoDB表,可以用 --single-transaction 避免锁表。
问题继续
加了--single-transaction后不需要锁表,是否还会导致mysqldump失败?答案依然是会。这次我们发现输出的错误是 "SHOW FIELDS FROM v1" 失败。由于show fields v1需要解析视图并列出执行结果的列信息,而表t1已经不存在因此报错。
问题是,为什么需要执行一个 SHOW FIELDS?
这就说到restore的依赖问题。
MySQL Tips: mysqldump生成导出文件时。同一个库内实体表先生成,之后是视图。多个实体表是按照字母升序生成,多个视图也是按字母升序生成。
这样就可能存在这样的情况,某个视图v1依赖视图v2,而v1的字母排序前于v2。比如视图名为x,而依赖的另一个视图名为y。这样在按顺序输出的时候,如果不做任何处理,在输出文件中就会先出现create view x ...而由于x依赖于y但y还没有生成,就会导致restore阶段执行失败。
MySQL Tips: mysqldump解决视图依赖问题的方法,就是在生成实体表阶段,如果碰到视图,则创建一个同名的临时实体表,该表的结果与视图完全相同。
配合的策略是在生成真正的视图前,先将临时实体表删除。这样在restore阶段,创建任何视图V1前,它所依赖的视图V2有两种情况:
1) 字母排序V2 > V1,则当前库中有一个名为V2的临时实体表,这样视图V1能够正常创建;
2) 字母排序V2 < V1,则此时视图V2已经存在,这样视图V1能够正常创建;
以上策略解决了视图循环依赖的问题,这个机制需要早生成实体表阶段得到视图执行结果的列名,因此需要执行一个 SHOW FIELDS。
实践建议
上面的分析说明了"为什么”,以下操作型的读者希望的实践建议:
1) 为避免无效视图影响导出,可以在调用mysqldump时增加--force参数,强行忽略此错误。这个忽略不会对数据造成影响;
2) 使用--result-file参数保存mysqldump结果,同时将所有控制台收到的返回都作为报警返回给调用端;
3) 检查 result-file的最后一行,若无“Dump completed on"字样,则返回严重错误,终止备份恢复流程。
相关推荐
详解 linux mysqldump 导出数据库、数据、表结构 导出完整的数据库备份: mysqldump -h127.0.0.1 -P3306 -uroot -ppassword --add-locks -q dbname > dbname.sql 说明:–add-locks:导出过程中锁定表,完成后回解锁...
`mysqldump`是一个强大的命令行工具,它允许用户备份、导出MySQL数据库的数据和结构。这个工具对于开发人员和系统管理员来说是必不可少的,因为它提供了在不同环境之间迁移数据的能力,也可以用于定期备份,防止数据...
1. 首先,创建一个新的表`new-table`,该表包含你需要导出的字段,如`a`, `b`, `c`。 2. 接着,执行SQL语句`INSERT INTO new-table (a,b,c) SELECT a,b,c FROM old-table;`,这会将`old-table`中对应的字段数据插入...
`mysqldump`工具就是MySQL提供的一个强大的命令行实用程序,用于导出数据库中的数据和/或结构。本文将深入探讨如何使用`mysqldump`只导出数据或只导出表结构。 首先,我们要理解`mysqldump`的基本用法。`mysqldump`...
mysqldump命令的用法 1、导出所有库 系统命令行 mysqldump -uusername -ppassword –all-databases > all.sql 2、导入所有库 mysql命令行 mysql>source all.sql; 3、导出某些库 系统命令行 mysqldump -uusername -...
首先,mysqldump是MySQL官方提供的一个命令行工具,用于导出数据库的结构和数据。它能够生成SQL语句脚本,这些脚本可以在需要时用于重新创建相同的数据库结构并填充数据。在DataGrip中,你可以利用这个工具来备份...
将通过`mysqldump`导出的SQL文件导入到另一个数据库中,你可以使用`mysql`客户端工具,如下: ```bash mysql 数据库名 文件名 ``` 或者 ```bash source /tmp/xxx.sql ``` 这会读取`xxx.sql`文件中的SQL语句并依次...
此外,`mysqldump`还提供了许多其他选项,如`--add-locks`在每个表导出前锁定表,`--add-drop-table`在每个`CREATE TABLE`语句前添加`DROP TABLE`,`--compress`在客户端和服务器之间压缩数据,以及`--delayed`使用`...
在MySQL数据库管理中,mysqldump工具是一个非常重要的组件,用于创建数据库的备份。然而,在实际操作过程中,我们可能会遇到各种备份失败的问题。本文主要针对一个特定的问题进行总结,即在执行mysqldump备份时,...
`mysqldump` 是MySQL提供的一个实用程序,用于备份数据库或其中的部分表。它可以生成SQL语句,这些语句可以在以后用于重建数据库或恢复数据。以下是一些基本的使用方法: 1. **导出整个数据库** ```bash ...
它转储一个或多个MySQL数据库以备份或传输到另一个SQL服务器。 mysqldump命令还可以生成CSV,其他分隔文本或XML格式的输出。 下图为镜像重命名后的镜像名为uoj,现在要把这个镜像中的mysql导出 运行如下命令: ...
2. 数据导出与导入:除了备份,`mysqldump`也可以用于将数据从一个数据库导出到另一个数据库,或者在同一数据库中导入数据。例如,`mysqldump -u username -p old_db | mysql -u username -p new_db`可以将`old_db`...
在MySQL数据库管理中,mysqldump是一个非常重要的工具,用于导出数据库的数据和结构。在实际操作中,我们可能会遇到一些问题,本篇文章将详细讨论这些常见的mysqldump数据导出问题及其解决方案。 首先,当我们遇到...
解决这一问题的方法是在mysqldump命令中添加`--skip-add-locks`参数,避免在导出过程中添加锁,从而防止执行失败: ``` mysqldump -u root -p root --skip-add-locks mydatabase mytable_2 -w "mytable_2.cust_id IN...
mysqldump 是一个用来将 MySQL 数据库中的数据导出到一个 SQL 文件的工具。mysqldump 命令可以将整个数据库、某个数据库、某个表或某些表导出到一个 SQL 文件中。mysqldump 的优点是可以将数据导出到一个 SQL 文件中...