MySQL优化之——备份和恢复

Posted wzzkaifa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL优化之——备份和恢复相关的知识,希望对你有一定的参考价值。

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46766919

备份

逻辑备份方法

使用mysqlDUMP命令备份

MYSQLDUMP是MYSQL提供的一个很实用的数据库备份工具。mysqldump命令运行时将数据库备份成一个文本文件,该文件里实际上包括了多个CREATE 和INSERT语句,使用这些语句能够又一次创建表和插入数据

MYSQLDUMP的语法和选项

mysqldump -u user -p pwd -h host dbname[tbname,[tbname...]]>filename.sql

选项/Option 作用/Action Performed
--add-drop-table
这个选项将会在每个表的前面加上DROP TABLE IF EXISTS语句,这样能够保证导回MySQL数据库的时候不会出错。由于每次导回的时候。都会首先检查表是否存在,存在就删除
--add-locks
这个选项会在INSERT语句中捆上一个LOCK TABLE和UNLOCK TABLE语句。

这就防止在这些记录被再次导入数据库时其它用户对表进行的操作 -c or - complete_insert 这个选项使得mysqldump命令给每个产生INSERT语句加上列(field)的名字。当把数据导出导另外一个数据库时这个选项非常实用。 --delayed-insert 在INSERT命令中增加DELAY选项 -F or -flush-logs 使用这个选项,在运行导出之前将会刷新MySQLserver的log. -f or -force 使用这个选项,即使有发生错误。仍然继续导出 --full 这个选项把附加信息也加到CREATE TABLE的语句中 -l or -lock-tables 使用这个选项,导出表的时候server将会给表加锁。

-t or -no-create- info 这个选项使的mysqldump命令不创建CREATE TABLE语句,这个选项在您仅仅须要数据而不须要DDL(数据库定义语句)时非常方便。 -d or -no-data 这个选项使的mysqldump命令不创建INSERT语句。 在您仅仅须要DDL语句时,能够使用这个选项。 --opt 此选项将打开全部会提高文件导出速度和创造一个能够更快导入的文件的选项。 -q or -quick 这个选项使得MySQL不会把整个导出的内容读入内存再运行导出。而是在读到的时候就写入导文件里。 -T path or -tab = path 这个选项将会创建两个文件,一个文件包括DDL语句或者表创建语句。还有一个文件包括数据。DDL文件被命名为table_name.sql,数据文件被命名为table_name.txt.路径名是存放这两个文件的文件夹。文件夹必须已经存在,而且命令的使用者有对文件的特权。

-w "WHERE Clause" or -where = "Where clause " 如前面所讲的,您能够使用这一选项来过筛选将要放到 导出文件的数据。 假定您须要为一个表单中要用到的帐号建立一个文件。经理要看今年(2004年)全部的订单(Orders)。它们并不正确DDL感兴趣,而且须要文件有逗号分隔,由于这样就非常easy导入到Excel中。

为了完毕这个任务,您能够使用以下的句子: bin/mysqldump –p –where "Order_Date >=\'2000-01-01\'" –tab = /home/mark –no-create-info –fields-terminated-by=, Meet_A_Geek Orders 这将会得到您想要的结果。

schema:模式 The set of statements, expressed in data definition language, that completely describe the structure of a data base. 一组以数据定义语言来表达的语句集,该语句集完整地描写叙述了数据库的结构。 SELECT INTO OUTFILE :

mysqldump提供了非常多选项。包含调试和压缩的,在这里仅仅是列举最实用的。

执行帮助命令mysqldump --help能够获得特定版本号的完整选项列表

user表示username称。

host表示登录用户的主机名称。

pwd为登录password;

dbname为须要备份的数据库名称。

tbname为dbname数据库中须要备份的数据表,能够指定多个须要备份的表;

右箭头“>”告诉mysqldump将备份数据库表定义和数据写入备份文件;

filename为备份文件的名称


1、使用mysqldump备份单个数据库中的全部表

数据库的记录是这种

打开cmd,然后运行以下的命令

 

能够看到C盘以下已经生成了school_2014-7-10.sql文件

使用editplus来打开这个sql文件

-- MySQL dump 10.13  Distrib 5.5.20, for Win32 (x86)
--
-- Host: 127.0.0.1    Database: school
-- ------------------------------------------------------
-- Server version    5.5.20-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE=\'+00:00\' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\'NO_AUTO_VALUE_ON_ZERO\' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `book`
--

DROP TABLE IF EXISTS `book`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `book` (
  `bookid` int(11) NOT NULL,
  `bookname` varchar(255) NOT NULL,
  `authors` varchar(255) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  `comment` varchar(255) DEFAULT NULL,
  `year_publication` year(4) NOT NULL,
  KEY `BkNameIdx` (`bookname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `book`
--

LOCK TABLES `book` WRITE;
/*!40000 ALTER TABLE `book` DISABLE KEYS */;
INSERT INTO `book` VALUES (1,\'鍓戝湥\',\'灏忔槑\',\'13\',\'hao\',2013);
/*!40000 ALTER TABLE `book` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `student`
--

DROP TABLE IF EXISTS `student`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `student` (
  `stuno` int(11) DEFAULT NULL,
  `stuname` varchar(60) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `student`
--

LOCK TABLES `student` WRITE;
/*!40000 ALTER TABLE `student` DISABLE KEYS */;
INSERT INTO `student` VALUES (2,\'xiaofang\'),(3,\'zhanghai\'),(6,\'haojie\');
/*!40000 ALTER TABLE `student` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `stuinfo`
--

DROP TABLE IF EXISTS `stuinfo`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `stuinfo` (
  `stuno` int(11) DEFAULT NULL,
  `class` varchar(60) DEFAULT NULL,
  `city` varchar(60) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `stuinfo`
--

LOCK TABLES `stuinfo` WRITE;
/*!40000 ALTER TABLE `stuinfo` DISABLE KEYS */;
INSERT INTO `stuinfo` VALUES (1,\'wuban\',\'henan\'),(2,\'liuban\',\'hebei\'),(3,\'qiban\',\'shandong\');
/*!40000 ALTER TABLE `stuinfo` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2014-07-23 22:04:16

能够看到。备份文件包括了一些信息。文件开头首先写明了mysqldump工具的版本。

然后是主机信息。以及备份的数据库名称,最后是mysqlserver的版本5.5.20

备份文件接下来的部分是一些SET语句,这些语句将一些系统变量赋值给用户定义变量,以确保被恢复的数据库的系统变量和原来

备份时的变量同样

比如:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

该set语句将当前系统变量character_set_client的值赋值给用户变量@OLD_CHARACTER_SET_CLIENT

备份文件的最后几行mysql使用set语句恢复server系统变量原来的值。比如:

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

该语句将用户定义变量@OLD_CHARACTER_SET_CLIENT 中保存的值赋值给实际的系统变量OLD_CHARACTER_SET_CLIENT 

备份文件里的“--”字符开头的行为凝视语句。以“/*!”开头、以“*/”结尾的语句为可运行的mysql凝视,这些语句能够被mysql运行

但在其它数据库管理系统将被作为凝视忽略,这能够提高数据库的可移植性

另外注意到,备份文件開始的一些语句以数字开头,这些数字代表了mysql版本号号,该数字告诉我们这些语句仅仅有在指定的mysql版本号

或者比该版本号高的情况下才干运行。

比如:40101,表明这些语句仅仅有在mysql版本号为4.01.01或者更高版本号的条件下才干够运行


2、使用mysqldump备份数据库中的某个表

备份school数据库里面的book表

 

-- MySQL dump 10.13  Distrib 5.5.20, for Win32 (x86)
--
-- Host: 127.0.0.1    Database: school
-- ------------------------------------------------------
-- Server version    5.5.20-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE=\'+00:00\' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\'NO_AUTO_VALUE_ON_ZERO\' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `book`
--

DROP TABLE IF EXISTS `book`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `book` (
  `bookid` int(11) NOT NULL,
  `bookname` varchar(255) NOT NULL,
  `authors` varchar(255) NOT NULL,
  `info` varchar(255) DEFAULT NULL,
  `comment` varchar(255) DEFAULT NULL,
  `year_publication` year(4) NOT NULL,
  KEY `BkNameIdx` (`bookname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `book`
--

LOCK TABLES `book` WRITE;
/*!40000 ALTER TABLE `book` DISABLE KEYS */;
INSERT INTO `book` VALUES (1,\'剑圣\',\'小明\',\'13\',\'hao\',2013);
/*!40000 ALTER TABLE `book` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2014-07-23 22:24:29

备份文件里的内容跟前面的介绍是一样的。唯一不同的是仅仅包括了book表的CREATE语句和INSERT语句


3、使用mysqldump备份多个数据库

假设要使用mysqldump备份多个数据库。须要使用--databases參数。

使用--databases參数之后,必须指定至少一个数据库的名称。多个数据库名称之间用空格隔开

使用mysqldump备份school库和test库

 备份文件中的内容,基本上跟第一个样例一样。可是指明了里面的内容那一部分属于test库。哪一部分属于school库

 

4、使用--all-databases參数备份系统中全部的数据库

使用--all-databases不须要指定数据库名称

运行完成之后会产生all_2014-7-10.sql的备份文件。里面会包括了全部数据库的备份信息

提示:假设在server上进行备份。而且表均为myisam。应考虑使用mysqlhotcopy

由于能够更快地进行备份和恢复

使用mysqlhotcopy,假设是Windows操作系统,须要先安装perl脚本组件才干使用,由于mysqlhotcopy是使用perl来编写的

提示

(1)假设你未使用--quick或者--opt选项,那么mysqldump将在转储结果之前把所有内容加载到内存中。这在你转储大数据量的数据库时将会有些问题。该选项默认是打开的,但能够使用--skip-opt来关闭它。
(2)使用--skip-comments能够去掉导出文件里的凝视语句
(3)使用--compact选项能够仅仅输出最重要的语句,而不输出凝视及删除表语句等等
(4)使用--database或-B选项,能够转储多个数据库,在这个选项名后的參数都被认定为数据库名

SQLSERVER逻辑备份

我发现SQLSERVER的备份概念并没有ORACLE和MYSQL那么多

我们通常都会使用以下的两个SQL语句来备份SQLSERVER数据库。比如备份test库

BACKUP DATABASE test TO DISK=\'c:\\test.bak\' 
BACKUP LOG test  TO DISK=\'c:\\test_log.bak\' 

第一个SQL是完整备份test库。假设加上WITH DIFFERENTIAL就是差异备份

第二个SQL是备份test库的日志

实际上从我眼中的理解,SQLSERVER就是将数据文件和必要的日志信息放入一个压缩包里面,类似于MYSQL的物理备份。直接拷贝文件,仅仅是MYSQL并没有进行打包压缩

SQLSERVER的逻辑备份

逻辑备份就是生成表定义脚本和数据插入脚本。SQLSERVER2008開始支持生成数据脚本。在SQLSERVER2008之前仅仅支持生成表定义脚本

我所用的数据库是SQLSERVER2012 SP1

选中须要生成脚本的数据库

比方我要导出test表的数据和表定义

要选择架构和数据,而且要选择索引,这样就会生成表的数据、定义、索引

生成的脚本例如以下

USE [sss]
GO
/****** Object:  Table [dbo].[test]    Script Date: 2014/7/24 11:27:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[test](
    [a] [int] NULL
) ON [PRIMARY]

GO
INSERT [dbo].[test] ([a]) VALUES (10)
GO

因为test表是没有不论什么索引的。所以脚本里看不到CREATE INDEX语句

实际上各种数据库的备份恢复方法都是大同小异的

ORACLE冷备份与恢复

逻辑备份和物理备份

1、导出create table 、create index、insert into 表等语句(逻辑备份)

mysql:mysqldump、load data infile、select into outfile

sqlserver:生成脚本、导入导出向导

oracle:(exp/imp)

2、直接拷贝文件(物理备份)

sqlserver:backup database语句、backup log语句、停SQLSERVER服务直接拷贝数据文件

mysql:mysqlhotcopy、innobackupex

oracle:rman、直接将关键性文件复制到另外的位置、(exp/imp)、(expdp/impdp)

相似点:上面的各种数据库的各种备份还原方法,每一种基本上都会有一个单独的工具来做

比如sqlserver导入导出向导就是一个单独的exe来做

oracle的rman也是一个单独的工具

冷备份和热备份:不管oracle、sqlserver、mysql都有冷备份和热备份的概念

冷备份事实上能够简单理解为:停止服务进行备份

热备份事实上能够简单理解为:不停止服务进行备份(在线)

上面的停止服务,正确的来讲应该是停止数据库的写入

为什么mysql的myisam引擎仅仅支持冷备份呢?

大家能够先想一下innodb引擎。innodb引擎是事务性存储引擎。每一条语句都会写日志,而且每一条语句在日志里面都有时间点

那么在备份的时候,mysql能够依据这个日志来进行redo和undo,将备份的时候没有提交的事务进行回滚,已经提交了的进行重做

可是myisam不行,myisam是没有日志的。为了保证一致性。仅仅能停机或者锁表进行备份

在书《MYSQL性能调优和架构设计》里面说到了事务的作用

 大家能够想一想。为什么sqlserver支持从某一个lsn或者时刻进行恢复数据库,他也是从日志里面读取日志的lsn号来进行恢复到某一个lsn时刻的数据或者某一个时刻的数据

假如没有事务日志。那么sqlserver是做不到时点还原的

热备份、冷备份

为什么SQLSERVER须要停止SQLSERVER服务才干够拷贝物理数据文件。为的都是保证数据一致性

 


物理备份方法

1、直接复制整个数据库文件夹

由于MYSQL表保存为文件方式,所以能够直接复制MYSQL数据库的存储文件夹以及文件进行备份。

MYSQL的数据库文件夹位置不一定同样,在Windows平台下,MYSQL5.6存放数据库的文件夹通常默觉得

C:\\Documents and Settings\\All User\\Application Data\\MySQL\\MYSQL Server 5.6\\data

或者其它用户自己定义的文件夹。

在Linux平台下,数据库文件夹位置通常为/var/lib/mysql/,不同Linux版本号下文件夹会有不同

这是一种简单、高速、有效的备份方式。

要想保持备份一致,备份前须要对相关表运行LOCK TABLES操作,然后对表运行

FLUSH TABLES。这样当复制数据库文件夹中的文件时,同意其它客户继续查询表。须要FLUSH TABLES语句来确保開始

备份前将全部激活的索引页写入磁盘。

当然,也能够停止MYSQL服务再进行备份操作

这样的方法尽管简单。但并非最好的方法。

由于这样的方法对INNODB存储引擎的表不适用。使用这样的方法备份的数据最好还原

到同样版本号的server中。不同的版本号可能不兼容。

注意:在mysql版本号中,第一个数字表示主版本号号。主版本号号同样的MYSQL数据库文件格式同样

2、使用mysqlhotcopy工具高速备份

mysqlhotcopy是一个perl脚本。最初由Tim Bunce编写并提供。

他使用LOCK TABLES 、FLUSH TABLES和cp或scp

来高速备份数据库。他是备份数据库或单个表的最快途径,但他仅仅能执行在数据库文件夹所在机器上。而且仅仅能备份myisam类型的表。

语法

mysqlhotcopy db_name_1,...db_name_n /path/to/new_directory

db_name_1...n代表要备份的数据库的名称;

path/to/new_directory指定备份文件文件夹

演示样例

在Linux以下使用mysqlhotcopy备份test库到/usr/backup

mysqlhotcopy -u root -p test /usr/backup

要想运行mysqlhotcopy,必须可以訪问备份的表文件,具有那些表的SELECT权限、RELOAD权限(以便可以运行FLUSH TABLES)

和LOCK TABLES权限

提示:mysqlhotcopy仅仅是将表所在文件夹拷贝到还有一个位置,仅仅能用于备份myisam和archive表。

备份innodb表会出现错误信息

因为他复制本地格式的文件。故也不能移植到其它硬件或操作系统下


 还原

逻辑还原

1、使用mysql命令进行还原

对于已经备份的包括CREATE、INSERT语句的文本文件,能够使用myslq命令导入数据库中

备份的sql文件里包括CREATE、INSERT语句(有时也会有DROP语句)。

mysql命令能够直接运行文件里的这些语句

其语法例如以下:

mysql -u user -p [dbname]<filename.sql

user是运行backup.sql中语句的username;-p表示输入用户password;dbname是数据库名

假设filename.sql文件为mysqldump工具创建的包括创建数据库语句的文件,运行的时候不须要指定数据库名

用mysql命令将school_2014-7-10.sql文件里的备份导入到数据库中

mysql -u root -h 127.0.0.1 -p school<c:\\school_2014-7-10.sql

运行语句之前我们必须建好school数据库,假设不存在恢复过程将会出错。

能够看到表数据都已经导入到数据库了

 

假设已经登录mysql,那么能够使用source命令导入备份文件

使用source命令导入备份文件school_2014-7-10.sql

运行source命令前必须使用use 语句选择好数据库,不然会出现ERROR 1046(3D000):NO DATABASE SELECTED 的错误

另一点要注意的是仅仅能在cmd界面下运行,不能在mysql工具里面运行source命令,否则会报错

由于cmd是直接调用mysql.exe来运行命令的

而这些mysql 编辑工具仅仅是利用mysql connector连接mysql。来管理mysql并非直接调用mysql.exe。所以运行source会报错


物理还原

2、直接拷贝到数据库文件夹

假设数据库通过复制数据库文件备份,能够直接复制备份文件到MYSQL数据文件夹下实现还原。

通过这样的方式还原时,

必须保证备份数据的数据库和待还原的数据库server的主版本同样。

并且这样的方式仅仅对MYISAM引擎有效,对于innodb引擎的表不可用

运行还原曾经关闭mysql服务。将备份的文件或文件夹覆盖mysql的data文件夹。启动mysql服务。

对于Linux操作系统来说。复制完文件须要将文件的用户和组更改为mysql执行的用户和组,通经常使用户是mysql,组也是mysql


3、mysqlhotcopy高速恢复

mysqlhotcopy备份后的文件也能够用来恢复数据库,在mysqlserver停止执行时。将备份的数据库文件拷贝到mysql存放数据的位置

(mysql的data目录),又一次启动mysql服务就可以。

假设根用户运行该操作,必须指定数据库文件的全部者,输入语句例如以下:

chown -R mysql.mysql /var/lib/mysql/dbname

从mysqlhotcopy复制的备份恢复数据库

cp -R /usr/backup/test  usr/local/mysql/data

运行完该语句,重新启动server。mysql将恢复到备份状态

注意:假设须要恢复的数据库已经存在,则在使用DROP语句删除已经存在的数据库之后,恢复才干成功。

另外mysql不同版本号之间必须兼容,恢复之后的数据才干够使用!


数据库迁移

数据库迁移就是把数据从一个系统移动到还有一个系统上。

迁移的一般原因:

1、须要安装新的数据库server

2、mysql版本号更新

3、数据库管理系统变更(从SQLSERVER迁移到mysql)

同样版本号的MYSQL数据库之间迁移

同样版本号mysql数据库间的迁移就是主版本号号同样的mysql数据库直接进行数据库移动。

前面解说备份和还原的时候,知道最简单的方法就是复制数据库文件文件夹,可是这样的方法仅仅适合于myisam表

对于innodb表,不能直接拷贝文件来备份数据库

最经常使用的方法是使用mysqldump导出数据,然后在目标数据库server使用mysql命令导入

将www.abc.com主机上的mysql数据库所有迁移到www.bcd.com主机上。

在www.abc.com主机上运行下面命令:

mysqldump -h www.abc.com -u root -p dbname |
mysql -h www.bcd.com -u root -p

mysqldump导入的数据直接通过管道符|。传给mysql命令导入到主机www.bcd.com数据库中,dbname为须要迁移的数据库名称

假设要迁移所有数据库。能够使用--all -databases參数


不同版本号的mysql数据库之间的迁移

由于数据库升级。须要将旧版本号mysql数据库中的数据迁移到新版本号数据库中。

mysqlserver升级,须要先停止服务,然后卸载旧版本号。并安装新版本号的mysql。这样的更新方法非常easy。

假设想保留旧版本号中的用户訪问控制信息。则须要备份mysql的mysql库。

在新版本号mysql安装完毕后,又一次读入mysql备份文件里的信息

旧版本号和新版本号的mysql可能使用不同的默认字符集,比如mysql.4.x中大多数使用latin1作为默认字符集。

而mysql5.x的默认字符集为utf8。

假设数据库中有中文数据,迁移过程中须要对默认字符集进行改动,不然可能无法正常显示结果

新版本号对旧版本号有一定兼容性。

从旧版本号的mysql向新版本号mysql迁移时,对于myisam引擎的表,能够直接复制数据库文件,

也能够用mysqlhotcopy工具、mysqldump工具。

对于innodb引擎的表一般仅仅能使用mysqldump将数据导出。

然后使用mysql命令导入目标server。

从新版本号向旧版本号mysql迁移数据时要小心,最好使用mysqldump命令导出。然后导入目标数据库中。


不同数据库之间的迁移

不同类型的数据库之间的迁移,是指把mysql数据库迁移到其它的数据库,比如从mysql迁移到oracle,从oracle迁移到mysql

从mysql迁移到SQLSERVER等。

迁移之前。须要了解不同数据库的结构,比較他们的差异。不同数据库定义同样类型的数据的keyword可能不同。

比如:mysql中日期字段分为DATE 和TIME两种,而ORACLE的日期字段仅仅有DATE。

数据库迁移能够使用一些工具,比如,在Windows系统下。能够使用MyODBC实现mysql和SQLSERVER之间的迁移(使用SQLSERVER导入导出向导)

mysql官方提供的工具:MYSQL Migration Toolkit也能够在不同数据库间进行数据迁移。


表的导入导出

MYSQL数据库能够将数据导出成sql文本文件、xml文件、html文件。相同这些导出文件也能够导入到MYSQL数据库中

一般异构数据库迁移都是採用文本文件的方式来导数据

导出 

1、用SELECT...INTO OUTFILE导出文本文件

mysql导出数据时,同意使用包括表定义的select语句进行数据的导出操作

该文件被创建在server主机上,因此必须有文件写入权限(FILE权限),才干使用此语法

SELECT INTO…OUTFILE语法:

select columnlist  from Table WHERE condition  into outfile \'filename\' [OPTIONS]
fields terminated by \'VALUE\'
fields [OPTIONALLY]  ENCLOSED BY \'VALUE\'
fields ESCAPED BY \'VALUE\'
lines STARTING by \'VALUE\'
lines terminated by \'VALUE\'

into outfile语句的作用就是把前面select语句查询出来的结果导出到名称为“filename”的外部文件里

[OPTIONS]部分为可选參数。[OPTIONS]部分的语法包含FILED和LINES子句,其可能取值为:

● fields子句:在FIELDS子句中有三个子句:TERMINATED BY、 [OPTIONALLY] ENCLOSED BY和ESCAPED BY。

假设指定了FIELDS子句,则这三个子句中至少要指定一个。
(1)TERMINATED BY用来指定字段值之间的符号,比如,“TERMINATED BY \',\'”指定了逗号作为两个字段值之间的标志,默觉得“\\t”制表符。
(2)ENCLOSED BY子句用来指定包裹文件里字符值的符号,比如,“ENCLOSED BY \' " \'”表示文件里字符值放在双引號之间,

若加上keywordOPTIONALLY表示全部的值都放在双引號之间。则仅仅有CHAR和VARCHAR等字符数据字段被包含。

(3)ESCAPED BY子句用来指定转义字符,比如,“ESCAPED BY \'*\'”将“*”指定为转义字符,代替“\\”,如空格将表示为“*N”。
● LINES子句:在LINES子句中使用TERMINATED BY指定一行结束的标志,如“LINES TERMINATED BY \'?\'”表示一行以“?”作为结束标志,默认值为“\\n”。

 TERMINATED BY也是相同的原理

FIELDS子句和LINES子句都是自选的,可是假设两个都被指定了。FIELDS子句必须位于LINES子句的前面

SELECT INTO…OUTFILE仅仅能在本机运行。假设要在其它server上导出数据。则须要使用以下命令来生成文件

mysql -e "select ...">filename

-e, --execute=name  Execute command and quit. (Disables --force and history

SELECT INTO…OUTFILE是LOAD DATA INFILE的补语。用于语句的OPTIONS部分的语法包含部分FIELDS子句和LINES子句

这些子句与LOAD DATA INFILE语句同一时候使用

使用SELECT INTO…OUTFILE将test数据库中的person表的记录导出到文本文件

输入命令例如以下

SELECT * FROM test.person  INTO  OUTFILE  "C:\\person0.txt" ;

因为指定了INTO OUTFILE 子句,SELECT将查询出来的3个字段的值保存到C:\\person0.txt文件,打开文件内容例如以下

1    green    29    lawer
2    suse    26    dancer
3    evans    27    sports man
4    mary    26    singer

能够看到默认情况下,MYSQL使用制表符“\\t”分隔不同的字段,字段没有被其它字符括起来

另外在Windows平台下。使用记事本打开该文件,显示的格式与这里并不同样。这是由于Windows系统下回车换行为“\\r\\n”

默认换行符为“\\n”,因此会在person.txt中可能看到类似黑色方块的字符,全部的记录也会在同一行显示

默认情况下,NULL值会显示为“\\N”,转义字符会显示为“\\”

使用SELECT ..INTO OUTFILE将test库中的person表中的记录导出到文本文件。使用FIELDS选项和LINES选项。要求字段之间

使用逗号“,”间隔。全部字段值用双引號括起来,定义转移字符为单引號“\\\'”

SELECT * FROM test.person  INTO  OUTFILE  "C:\\person1.txt" 
FIELDS
TERMINATED BY \',\'
ENCLOSED BY \'\\\'\'
ESCAPED BY \'\\\'\'
LINES
TERMINATED BY \'\\r\\n\';

在C盘下生成的person1文件内容

\'1\',\'green\',\'29\',\'lawer\'
\'2\',\'suse\',\'26\',\'dancer\'
\'3\',\'evans\',\'27\',\'sports man\'
\'4\',\'mary\',\'26\',\'singer\'

FIELDS  TERMINATED BY \',\'表示字段之间用逗号分隔

ENCLOSED BY \'\\\'\'表示每一个字段用双引號括起来

ESCAPED BY \'\\\'\'表示将系统默认的转移字符替换为单引號

LINES TERMINATED BY \'\\r\\n\'表示每行以回车换行符结尾。保证每一条记录占一行


2、用mysqldump命令导出文本文件

除了使用SELECT...INTO OUTFILE导出文本文件之外。也能够使用mysqldump

mysqldump不仅能够将数据导出包括CREATE、INSERT的sql文件,也能够导出为纯文本文件

mysqldump创建一个包括创建表的CREATE TABLE语句的tablename.sql文件,和一个包括其数据

的tablename.txt文件。mysqldump导出文本文件的基本的语法例如以下

mysqldump -T path -u root -p dbname [tables][OPTIONS]
--fields-terminated-by=
--fields-enclosed-by=
--fields-optionally-enclosed-by=
--fields-escaped-by=
--lines-terminated-by=

仅仅有指定了-T參数才干够导出纯文本文件;path表示导出数据的文件夹

tables为指定要导出的表名称。假设不指定,将导出dbname的全部表

基本上每一个选项跟SELECT ..INTO OUTFILE语句中的OPTIONS各个參数设置同样

不同的是。等号后面的value值不要用引號括起来

使用mysqldump将test库的person表的记录导出到文本文件。运行的命令例如以下

mysqldump -T C:\\ -u root -h 127.0.0.1  -p test person

这里要注意的是,路径这里不能先创建好person.txt文件,否则会报错,跟SELECT ..INTO OUTFILE语句是一样的

在C盘会生成一个person.txt文件和person.sql文件,内容例如以下

person.sql

-- MySQL dump 10.13  Distrib 5.5.28, for Win32 (x86)
--
-- Host: 127.0.0.1    Database: test
-- ------------------------------------------------------
-- Server version    5.5.28-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE=\'+00:00\' */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=\'\' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `person`
--

DROP TABLE IF EXISTS `person`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `person` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(20) NOT NULL,
  `Age` int(10) unsigned DEFAULT NULL,
  `job` varchar(90) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2014-07-27 23:56:01

person.sql的内容跟之前解释的是一样的

person.txt

1    green    29    lawer
2    suse    26    dancer
3    evans    27    sports man
4    mary    26    singer 


3、使用mysql命令导出文本文件

mysql是一个功能丰富的工具命令,使用mysql还能够在命令行模式下运行SQL指令,将查询结果导入到文本文件里。

相比mysqldump,mysql工具导出的结果可读性更强

假设mysqlserver是单独的机器,用户是在一个client上进行操作,用户要把数据结果导入到client机器上,能够使用mysql -e语句

基本格式例如以下:

mysql -u root -p --execute="SELECT 语句" dbname >filename.txt

该命令使用--execute 选项,表示运行该选项后面的语句并退出。后面的语句必须用双引號括起来

dbname为要导出的数据库名称,导出的文件里不同列之间使用制表符分隔,第一行包括了字段名称

使用mysql命令。导出test库的person表记录到文本文件,输入语句例如以下:

mysql -u root -p --execute="SELECT * FROM person;" test>C:\\person3.txt

person3.txt的内容例如以下

ID    Name    Age    job
1    green    29    lawer
2    suse    26    dancer
3    evans    27    sports man
4    mary    26    singer

能够看到,person3.txt文件里包括了每一个字段的名称和各条记录,假设某行记录字段非常多,可能一行不能全然显示,能够使用

--vertical參数。将每条记录分为多行显示

使用mysql命令导出test库的person表使用--vertical參数显示

mysql -u root -p  --vertical --execute="SELECT * FROM person;" test>C:\\person4.txt

*************************** 1. row ***************************
  ID: 1
Name: green
 Age: 29
 job: lawer
*************************** 2. row ***************************
  ID: 2
Name: suse
 Age: 26
 job: dancer
*************************** 3. row ***************************
  ID: 3
Name: evans
 Age: 27
 job: sports man
*************************** 4. row ***************************
  ID: 4
Name: mary
 Age: 26
 job: singer

假设person表中记录内容太长,这样显示将会更加easy阅读

使用mysql命令导出test库的person表记录到html文件,输入语句例如以下

mysql -u root -p --html --execute="SELECT * FROM PERSON;"test >C:\\person5.html

假设要导出为xml文件。那么使用--xml选项

使用mysql命令导出test库的person表的中记录到xml文件

mysql -u root -p --xml --execute="SELECT * FROM PERSON;" test >C:\\person6.xml

<?xml version="1.0"?

> <resultset statement="SELECT * FROM PERSON" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <row> <field name="ID">1</field> <field name="Name">green</field> <field name="Age">29</field> <field name="job">lawer</field> </row> <row> <field name="ID">2</field> <field name="Name">suse</field> <field name="Age">26</field> <field name="job">dancer</field> </row> <row> <field name="ID">3</field> <field name="Name">evans</field> <field name="Age">27</field> <field name="job">sports man</field> </row> <row> <field name="ID">4</field> <field name="Name">mary</field> <field name="Age">26</field> <field name="job">singer</field> </row> </resultset>


 导入

1、使用LOAD DATA INFILE 方式导入文本文件

mysql同意将数据导出到外部文件,也能够从外部文件导入数据。

MYSQL提供了一些导入数据的工具,这些工具有:LOAD DATA语句、source命令、mysql命令

LOAD DATA INFILE语句用于快速地从一个文本文件里读取行。并装入一个表中。文件名必须为文字字符串

语法例如以下:

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE \'file_name.txt\' 
[REPLACE | IGNORE] 
INTO TABLE tbl_name 
[FIELDS 
[TERMINATED BY \'string\'] 
[[OPTIONALLY] ENCLOSED BY \'char\'] 
[ESCAPED BY \'char\' ] 
] 
[LINES 
[STARTING BY \'string\'] 
[TERMINATED BY \'string\'] 
] 
[IGNORE number LINES] 
[(col_name_or_user_var,...)] 
[SET col_name = expr,...]] 

load data infile语句从一个文本文件里以非常高的速度读入一个表中。
使用这个命令之前。mysqld进程(服务) 必须已经在执行。
当读取的文本文件不在本机,而是位于server上的文本文件时,使用load data infile语句,在server主机上你必须有file的权限。

1 、假设你指定关键词low_priority,那么MySQL将会等到没有其它人读取这个表的时候,
才插入数据。比如例如以下的命令:

load data low_priority infile "/home/mark/data.sql" into table Orders;

2 、假设指定local关键词,则表明读取的文件在本机,那么必须指定local參数。

3 、replace和ignore參数控制对现有表的唯一键记录反复的处理。

假设你指定replace,新行将取代有同样的唯一键值的现有行。

 (1)假设你指定ignore,跳过有唯一键的现有行的反复行的输入。

 (2)假设你不指定不论什么一个选项,当找到反复键时,出现一个错误。而且文本文件的余下部分被忽略。

FIELDS  TERMINATED BY \',\'表示字段之间用逗号分隔

ENCLOSED BY \'\\\'\'表示每一个字段用双引號括起来

ESCAPED BY \'\\\'\'表示将系统默认的转移字符替换为单引號

LINES STARTING BY \'\'表示每行数据开头的字符,能够为单个或多个。默认不是有不论什么字符

LINES TERMINATED BY \'\\r\\n\'表示每行以回车换行符结尾,保证每一条记录占一行

[IGNORE number LINES] 选项表示忽略文件開始处的行数。number表示忽略的行数。

基本上格式上的參数跟SELECT...INTO OUTFILE是一样的

使用LOAD DATA命令将C:\\person0。txt文件里的数据导入到test库中的test表

LOAD DATA INFILE \'C:\\person0.txt\' INTO TABLE test.person

 先删除person表里的数据,然后运行LOAD DATA命令

使用mysqlimport命令导入文本文件

2、使用mysqlimport命令导入文本文件

mysqlimport是一个单独的exe。他提供了很多与LOAD DATA INFILE语句同样的功能

大多数选项直接相应LOAD DATA INFILE子句

mysqlimport的语法例如以下

mysqlimport -u root -p dbname filename.txt  [OPTIONS]
--[OPTIONS] 选项
FIELDS  TERMINATED BY \'value\'
ENCLOSED BY \'value\'
ESCAPED BY \'value\'
LINES TERMINATED BY \'value\'
IGNORE LINES

[OPTIONS] 选项基本上与LOAD DATA INFILE 语句是一样的,这里不做介绍了

mysqlimport不能指定导入的表名称,表名称由导入文件名称称确定。即文件名称作为表名,导入数据之前该表必须存在

使用mysqlimport命令将C:\\文件夹下person.txt文件内容导入到test库

先删除test库的person表的数据

DELETE FROM `person`;

person.txt文件内容

1    green    29    lawer
2    suse    26    dancer
3    evans    27    sports man
4    mary    26    singer

命令例如以下

mysqlimport -u root -p  test C:\\person.txt

导入成功

mysqlimport的常见选项:

显示帮助消息并退出。

·         --columns=column_list, -c column_list

该选项採用用逗号分隔的列名作为其值。

列名的顺序指示怎样匹配数据文件列和表列。 · --compress,-C 压缩在client和server之间发送的全部信息(假设二者均支持压缩)。 · ---debug[=debug_options],-# [debug_options] 写调试日志。debug_options字符串一般是\'d:t:o,file_name\'。 · --delete。-D 导入文本文件前清空表。 · --fields-terminated-by=...,--fields-enclosed-by=...,--fields-optionally-enclosed-by=...。--fields-escaped-by=...,--lines-terminated-by=... 这些选项与LOAD DATA INFILE对应子句的含义同样。

參见13.2.5节,“LOAD DATA INFILE语法”。 · --force,-f 忽视错误。

比如,假设某个文本文件的表不存在。继续处理其他文件。不使用--force,假设表不存在则mysqlimport退出。 · --host=host_name,-h host_name 将数据导入给定主机上的MySQLserver。默认主机是localhost。

· --ignore。-i 參见--replace选项的描写叙述。 · --ignore-lines=n 忽视数据文件的前n行。 · --local,-L 从本地client读入输入文件。 · --lock-tables,-l 处理文本文件前锁定全部表以便写入。这样能够确保全部表在server上保持同步。

· --password[=password],-p[password] 当连接server时使用的密码。

假设使用短选项形式(-p)。选项和 密码之间不能有空格。

假设在命令行中--password或-p选项后面没有 密码值,则提示输入一个密码。

· --port=port_num,-P port_num 用于连接的TCP/IP端口号。

· --protocol={TCP | SOCKET | PIPE | MEMORY} 使用的连接协议。 · --replace,-r --replace和--ignore选项控制复制唯一键值已有记录的输入记录的处理。假设指定--replace,新行替换有同样的唯一键值的已有行。假设指定--ignore,复制已有的唯一键值的输入行被跳过。假设不指定这两个选项,当发现一个复制键值时会出现一个错误,而且忽视文本文件的剩余部分。 · --silent。-s 沉默模式。仅仅有出现错误时才输出。 · --socket=path,-S path 当连接localhost时使用的套接字文件(为默认主机)。 · --user=user_name,-u user_name 当连接server时MySQL使用的username。 · --verbose,-v 冗长模式。打印出程序操作的具体信息。 · --version,-V 显示版本号信息并退出。

提示:

LOAD DATA INFILE语句中有一个mysqlimport工具中没有特点: 

LOAD DATA INFILE 能够按指定的字段把文件导入到数据库中。

当我们要把数据的一部分内容导入的时候,这个特点就非常重要。

例如说,我们要从Access数据库升级到MySQL数据库的时候,须要增加一些字段(列/字 段/field)到MySQL数据库中。以适应一些额外的须要。 

这个时候,我们的Access数据库中的数据仍然是可用的。可是由于这些数据的字段(field)与MySQL中的不再匹配,因此而无法再使用mysqlimport工具。

虽然如此,我们仍然能够使用LOAD DATA INFILE,以下的样例显示了怎样向指定的字段(field)中导入数据:

LOAD DATA INFILE "/home/Order.txt" INTO TABLE Orders(Order_Number, Order_Date, Customer_ID); 

如您所见,我们能够指定须要的字段(fields)。

这些指定的字段依旧是以括号括起。由逗号分隔的,假设您遗漏了当中不论什么一个。MySQL将会提醒您^_^ 


怎样选择备份工具?

直接复制数据文件是最为直接、高速的备份方法,但缺点是基本上不能实现增量备份。

备份时必须确保没有使用这些表。假设在复制一个表的物理数据文件的同一时候server正在改动他,则复制无效。

备份文件时,最好关闭server,然后又一次启动server。为了保证数据的一致性,须要在备份文件前运行下面SQL

FLUSH TABLES WITH READ LOCK;

也就是把内存中的数据刷新到磁盘中,同一时候锁定数据表,以保证复制过程中不会有新的数据写入。

这样的方法备份出来的数据恢复非常easy。直接复制回原来的数据库文件夹下就可以

mysqlhotcopy是一个PERL程序,他使用LOCK TABLES、FLUSH TABLES和CP或SCP来高速备份数据库

他是备份数据库或单个表的最快的途径,但他仅仅能执行在数据库文件所在机器上,而且mysqlhotcopy仅仅能用于备份myisam表

mysqlhotcopy适合于小型数据库的备份。数据量不大,能够使用mysqlhotcopy程序每天进行一次全然备份

mysqldump将数据表导出为SQL脚本,在不同的MYSQL版本号之间升级时相对照较合适,这也是最经常使用的备份方法。

mysqldump比直接复制要慢些。


使用mysqldump备份整个数据库成功,把表和数据库删除了,但使用备份文件却不能恢复数据库?

出现这样的情况是由于备份的时候没有指定--databases參数。默认情况下,假设仅仅指定数据库名称,mysqldump

备份的是数据库中的全部表,而不包含数据库的创建语句,例如以下

mysqldump -u root -p booksdb >c:\\booksdb_2014-7-1.sql

该语句仅仅备份了booksdb数据库下的全部表。读者打开该文件,能够看到文件里不包括创建booksdb数据库

的CREATE DATABASE语句,因此假设把booksdb也删除了。使用该sql文件不能还原曾经的表。

还原时会出现ERROR 1046(3D000):NO DATABASE SELECTED 的错误信息

而以下的语句,数据库删除之后,能够正常还原备份时的状态

mysqldump -u root -p --databases booksdb>C:\\booksdb_db_2014-7-1.sql

该语句不仅备份了全部数据库下的表结构,并且包含创建数据库的语句


总结

这一节介绍了MYSQL中的备份和还原,还有数据库的迁移,异构数据库之间的迁移基本上都用导出文件文件的方法

假设是小数据量尚能够,假设数据量比較大,导出文本文件也会非常大,不是太可取

以上是关于MySQL优化之——备份和恢复的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 之数据备份及恢复

MySQL数据库之——日志和数据库内容的备份与恢复(妈妈再也不用担心数据丢失了)

MySQL之备份与恢复

MySQL学习笔记之七:数据的备份和恢复

mysql之备份与恢复

MySQL之Xtrabackup备份与恢复