2019-04-15 MySQL數據庫備份與恢復基礎實踐(1)

1. MySQL數據庫的備份與恢復

1.1 備份數據的意義

對于絕大多數企業來講,失去數據就相當于失去商機、失去產品、失去客戶,甚至會造成公司倒閉。

1.2 使用mysqldump進行數據庫備份實踐

1. 不帶參數備份單個數據庫
[root@oldboy ~]# mysql < /opt/bak.sql     ---先還原數據,由于前面在my.cnf配置了用戶密碼,所以這里和后面的例子都不用輸賬號密碼

范例:不加任何參數備份名字為oldboy的庫

[root@oldboy ~]# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 5.6.41 Source distribution
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use oldboy
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from test;    ---查看備份前的數據
+----+---------+
| id | name    |
+----+---------+
|  1 | oldboy  |
|  2 | oldgirl |
|  3 | inca    |
|  4 | zuma    |
|  5 | kaka    |
+----+---------+
5 rows in set (0.00 sec)

執行備份oldboy庫的命令:

[root@oldboy ~]# mysqldump oldboy > /opt/mysql_bak.sql

用egrep檢查備份結果:

[root@oldboy ~]# egrep -v "#|\*|--|^$" /opt/mysql_bak.sql     ---去掉注釋等特殊字符
DROP TABLE IF EXISTS `test`;    ---刪除表語句
CREATE TABLE `test` (    ---建表語句
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` char(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
LOCK TABLES `test` WRITE;
INSERT INTO `test` VALUES (1,'oldboy'),(2,'oldgirl'),(3,'inca'),(4,'zuma'),(5,'kaka');    ---插入語句
UNLOCK TABLES;
2. 加-B參數備份的實踐
[root@oldboy ~]# mysqldump -B oldboy > /opt/mysql_bak_B.sql 
[root@oldboy ~]# diff /opt/mysql_bak.sql /opt/mysql_bak_B.sql     ---使用diff或vimdiff比較不同得地方
18a19,26
> -- Current Database: `oldboy`
> --
> 
> CREATE DATABASE /*!32312 IF NOT EXISTS*/ `oldboy` /*!40100 DEFAULT CHARACTER SET utf8 */;
> 
> USE `oldboy`;
> 
> --
51c59
< -- Dump completed on 2019-02-07  7:18:33
---
> -- Dump completed on 2019-02-07  7:24:31

可以看到,加“B”參數的作用是增加創建數據庫和連接數據庫的語句。即如下這兩條語句:

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `oldboy` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `oldboy`;
3. 使用gzip壓縮備份數據庫的實踐
[root@oldboy ~]# mysqldump -B oldboy | gzip > /opt/mysql_bak_B.sql.gz    ---注意壓縮命令前要加管道
[root@oldboy ~]# ll /opt/
total 16
-rw-r--r--. 1 root root 2051 Feb  6 16:43 bak.sql
-rw-r--r--. 1 root root 2051 Feb  7 07:24 mysql_bak_B.sql    ---沒有壓縮的備份數據較大
-rw-r--r--. 1 root root  779 Feb  7 07:29 mysql_bak_B.sql.gz    ---壓縮過的數據庫備份小了很多
-rw-r--r--. 1 root root 1908 Feb  7 07:18 mysql_bak.sql

小結

  • 使用-B參數備份數據庫,會在備份的數據中增加建庫及use庫的語句
  • 使用-B參數備份數據庫,后面還可以直接接多個庫名,實現同時備份多個庫
  • 使用gzip命令壓縮備份的數據,備份的壓縮包是原來的1/3大小
4. musqldump命令工作原理

利用mysqldump命令備份數據的過程,實際上就是把數據(包括庫表)從MySQL庫里以SQL語句的形式直接輸出或者生成備份文件的過程,這種備份成SQL語句得方式稱為邏輯備份。
把備份的數據過濾掉注釋信息,剩下的都是SQL語句:

[root@oldboy ~]# egrep -v "#|\*|--|^$" /opt/mysql_bak.sql
DROP TABLE IF EXISTS `test`;    ---刪除表語句
CREATE TABLE `test` (    ---建表語句
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` char(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
LOCK TABLES `test` WRITE;
INSERT INTO `test` VALUES (1,'oldboy'),(2,'oldgirl'),(3,'inca'),(4,'zuma'),(5,'kaka');    ---插入語句
UNLOCK TABLES;

mysqldump這種邏輯備份的方式效率不是很高,在當下的生產場景中,多用于數據量不是很大得備份情況,例如30GB以內的數據。若在數據庫數據很大的時候采用此備份方式,所用的時間會很長,恢復的時間也會很長,因此,當數據大于30GB(參考值)后,建議選擇其他得諸如Xtrabackup的物理方式進行備份和恢復。

5. 備份多個庫

(1)備份多個庫的實踐

mysql> show databases;    ---查看當前數據庫里的庫信息
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| oldboy             |
| oldboy_utf8        |
| performance_schema |
+--------------------+
5 rows in set (0.01 sec)
mysql> quit
Bye
[root@oldboy ~]# mysqldump -B oldboy oldboy_utf8 | gzip > /opt/test.sql.gz    ---同時備份兩個庫
---使用-B參數表示后面可接多個庫,并且在備份文件里會增加use db,和create database db的信息
[root@oldboy ~]# mysqldump -B oldboy oldboy_utf8 mysql | gzip > /opt/all.sql.gz
---mysql5.5及以前版本備份mysql庫時需要加一個--events參數,否則會有警告信息
[root@oldboy ~]# ll /opt/all.sql.gz 
-rw-r--r--. 1 root root 181236 Feb  7 07:53 /opt/all.sql.gz
---備份的數據庫不能太小(例如幾字節),否則可能會由于命令或參數等導致備份結果有問題

(2)如何做分庫備份
分庫備份實際上就是每次只執行一個mysqldump備份命令語句備份一個庫,如果數據庫里有多個庫,就執行多條相同的語句來備份各個庫。

[root@oldboy ~]# mysql -e "show databases;" | egrep -v "_schema|Database"    ---取出需要備份的庫名列表
mysql
oldboy
oldboy_utf8
[root@oldboy ~]# mysql -e "show databases;" | egrep -v "_schema|Database" | sed -r 's#^(.*)#mysqldump -B \1 | gzip > /tmp/\1.sql.gz#g'    ---利用命令拼接成多個mysqldump備份
mysqldump -B mysql | gzip > /tmp/mysql.sql.gz
mysqldump -B oldboy | gzip > /tmp/oldboy.sql.gz
mysqldump -B oldboy_utf8 | gzip > /tmp/oldboy_utf8.sql.gz
[root@oldboy ~]# mysql -e "show databases;" | egrep -v "_schema|Database" | sed -r 's#^(.*)#mysqldump -B \1 | gzip > /tmp/\1.sql.gz#g' | bash
---最后管道對bash執行這些備份命令,就是一次分開備份多個庫了
[root@oldboy ~]# ll /tmp/*.sql.gz
-rw-r--r--. 1 root root 181064 Feb  7 08:03 /tmp/mysql.sql.gz
-rw-r--r--. 1 root root    779 Feb  7 08:03 /tmp/oldboy.sql.gz
-rw-r--r--. 1 root root    511 Feb  7 08:03 /tmp/oldboy_utf8.sql.gz
6. 備份單個表

當不加-B參數備份數據庫時,例如“mysqldump oldboy test”,mysqldump命令默認就會把oldboy當作庫,把test當作表,如果后面還有多個字符串,例如“mysqldump oldboy test test1”,那么除了oldboy為庫之外,其他的test、test1都是oldboy庫的表。

[root@oldboy ~]# mysqldump oldboy test > /tmp/oldboy_test.sql    ---僅備份oldboy庫里的test表
7. 備份多個表
[root@oldboy ~]# mysqldump mysql user db > /tmp/mysql.sql
[root@oldboy ~]# egrep -v "#|\*|--|^$" /tmp/mysql.sql    ---這里不能用-B參數,因為庫后面的兩個都是表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (    ---user表
  `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
  `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '',
  `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ssl_cipher` blob NOT NULL,
  `x509_issuer` blob NOT NULL,
  `x509_subject` blob NOT NULL,
  `max_questions` int(11) unsigned NOT NULL DEFAULT '0',
  `max_updates` int(11) unsigned NOT NULL DEFAULT '0',
  `max_connections` int(11) unsigned NOT NULL DEFAULT '0',
  `max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
  `plugin` char(64) COLLATE utf8_bin DEFAULT 'mysql_native_password',
  `authentication_string` text COLLATE utf8_bin,
  `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges';
LOCK TABLES `user` WRITE;
UNLOCK TABLES;
DROP TABLE IF EXISTS `db`;
CREATE TABLE `db` (    ---db表
  `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
  `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '',
  `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
  PRIMARY KEY (`Host`,`Db`,`User`),
  KEY `User` (`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges';
LOCK TABLES `db` WRITE;
INSERT INTO `db` VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'),('%','test\\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y','Y'),('localhost','oldboy','test','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'),('192.168.9.%','blog','blog','Y','Y','Y','Y','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N');
UNLOCK TABLES;

企業中可能會存在這樣的情況,一個庫里有大表也有小表,有時可能需要只恢復某一個小表,上面實現的多表備份文件很難拆開,就像沒有分庫那樣會導致恢復某一個小表也很麻煩。
這里的思路和分庫備份一樣,每執行一條語句就備份一個表,生成不同的數據文件即可:

mysqldump oldboy test > oldboy_test.sql
mysqldump oldboy test1 > oldboy_test1.sql
......

分表備份的缺點:數據文件多,很碎,一旦需要全部恢復又很麻煩。
解決辦法如下:

  • 做一個完整全備,再做一個分庫分表備份
  • 雖然文件多、碎,但可以利用腳本批量操作多個SQL文件
8. 企業備份案例解析

如果多個庫或多個表備份到了一個文件里,那么這種情況下,如何恢復單個庫或者單個表?
解決辦法如下:

  • 找個第三方測試庫,將所有備份都導入到這個測試庫里,然后把需要的單庫或表再備份出來,最后恢復到需要恢復的正式庫里
  • 如果是單表恢復,還可以執行“grep -w 表名 bak.sql > 表名.sql”命令

當然,最好是備份時提前采用分庫分表備份

9. 備份數據庫表結構(不包含數據)

利用mysqldump的-d參數可以只備份表的結構,即建表的語句

[root@oldboy ~]# mysqldump -d oldboy > /opt/oldboy.sql    ---備份oldboy庫的所有表結構,也可以指定某一個表
[root@oldboy ~]# egrep -v "#|\*|--|^$" /opt/oldboy.sql 
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` char(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
10. 只備份數據庫的數據(不包含表結構)

利用-t參數備份數據庫表的數據(SQL語句形式):

[root@oldboy ~]# mysqldump -t oldboy > /opt/oldboy1.sql 
[root@oldboy ~]# egrep -v "#|\*|--|^$" /opt/oldboy1.sql 
LOCK TABLES `test` WRITE;
INSERT INTO `test` VALUES (1,'oldboy'),(2,'oldgirl'),(3,'inca'),(4,'zuma'),(5,'kaka');
UNLOCK TABLES;
11. 同時將數據和表結構分離導出

利用-T參數可以實現將數據和表結構同時分離備份。不過有可能會碰到如下情況:

[root@oldboy ~]# mysqldump oldboy test --compact -T /tmp/
---5.6版本因為安全權限問題不能直接導出了
mysqldump: Got error: 1290: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement when executing 'SELECT INTO OUTFILE'
---提示是因為--secure-file-priv選項所導致

如果依然想以此方式備份數據,那么可以調整配置文件參數并重啟MySQL:

[root@oldboy ~]# vi /etc/my.cnf
secure_file_priv=''    ---在[mysqld]模塊下增加
:wq
[root@oldboy ~]# /etc/init.d/mysqld restart
Shutting down MySQL... SUCCESS! 
Starting MySQL...... SUCCESS! 

備份的命令如下:

[root@oldboy ~]# mysqldump oldboy test --compact -T /tmp/
--compact是減少無用輸出的意思
[root@oldboy ~]# ll /tmp/test*
-rw-r--r--. 1 root  root  331 Feb  7 13:55 /tmp/test.sql
-rw-rw-rw-. 1 mysql mysql  40 Feb  7 13:55 /tmp/test.txt
[root@oldboy ~]# cat /tmp/test.sql     ---建表的語句
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `name` char(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
[root@oldboy ~]# cat /tmp/test.txt     ---純文本數據,非SQL語句
1   oldboy
2   oldgirl
3   inca
4   zuma
5   kaka

mysqldump參數小結:

  • -d參數的作用是只備份庫表的結構(SQL語句形式)
  • -t參數的作用是只備份表內的數據(SQL語句形式)
  • -T將建表和數據分離成不同的文件,數據是純文本,表結構是SQL語句
12. 刷新binlog文件參數(-F)

(1)binlog是什么
Binlog是一個二進制格式的文件,用于記錄用戶對數據庫更新得SQL語句信息,例如更改數據庫庫表和更改表內容得SQL語句都會記錄到binlog里。
(2)binlog對于備份的作用
假設每天0點對數據庫進行備份,那么在兩次備份之間就有24小時的數據沒有備份,在這期間如果數據庫發生故障,使用mysqldump全量恢復也只能恢復到當日0點,但是有了binlog文件,就可以將兩次完整備份間隔之間的數據還原,因為binlog文件里的數據就是寫入數據庫的數據,使用binlog文件恢復數據,我們稱之為二進制增量數據恢復。
(3)為什么要刷新binlog
刷新(切割)binlog日志的目的就是確定全備和增量備(binlog文件)的臨界點,當全備完成后,全備時刻以前的binlog文件就沒用了,但是全備以后到下一次全備之前的數據就是十分重要的,這部分數據就存在于binlog文件里,因此在進行全備時需要找到全備之后和binlog增量之間的臨界點,使得恢復時,需要的binlog文件數據一條不多(不能和全備的內容重合),一條不少(全備后的所有數據都要有)。

使用-F刷新日志的原理圖

(4)如何開啟binlog功能
binlog文件生效需要一個參數:log_bin,編輯配置文件增加log_bin參數即可,注意,MySQL5.6版本變成了下劃線連接得格式(MySQL5.6以前是中杠)。

[root@oldboy ~]# vi /etc/my.cnf
log_bin    ---把默認的注釋去掉即可,默認binlog文件名前綴為“主機名-bin”,也可以自定義名字,例如log_bin = mysql_bin
:wq
[root@oldboy ~]# /etc/init.d/mysqld restart    ---重啟mysql服務
Shutting down MySQL.. SUCCESS! 
Starting MySQL. SUCCESS! 
[root@oldboy ~]# ll -rt /application/mysql/data/oldboy-bin*
-rw-rw----. 1 mysql mysql  20 Feb  7 21:35 /application/mysql/data/oldboy-bin.index    ---索引文件
-rw-rw----. 1 mysql mysql 120 Feb  7 21:35 /application/mysql/data/oldboy-bin.000001    ---日志文件

binlog日志切割就是確定全備和binlog增量備份的臨界點
(5)使用-F刷新binlog日志
使用-F將會從備份后的時刻起重新記錄binlog日志文件,將來增量恢復從新的binlog日志文件開始即可。
例如,早上10點丟失數據需要恢復數據,則數據恢復步驟具體如下:
1)將0:00點時刻備份的全備數據還原到數據庫,這個時候數據就恢復到了當日0:00點
2)0:00點-10:00點丟失的數據,就要從全備后當天的所有binlog里恢復,而使用-F切割日志,就是找到0:00點這個時刻全備和binlog接縫的起始binlog文件。

[root@oldboy ~]# mysqldump -F -B oldboy | gzip > /opt/bak_$(date +%F).sql.gz    ---帶-F備份
[root@oldboy ~]# ll -rt /application/mysql/data/oldboy-bin*
-rw-rw----. 1 mysql mysql 168 Feb  7 21:46 /application/mysql/data/oldboy-bin.000001
-rw-rw----. 1 mysql mysql 120 Feb  7 21:46 /application/mysql/data/oldboy-bin.000002    ---新binlog
-rw-rw----. 1 mysql mysql  40 Feb  7 21:46 /application/mysql/data/oldboy-bin.index
[root@oldboy ~]# mysqldump -F -B oldboy | gzip > /opt/bak_$(date +%F).sql.gz
[root@oldboy ~]# ll -rt /application/mysql/data/oldboy-bin*
-rw-rw----. 1 mysql mysql 168 Feb  7 21:46 /application/mysql/data/oldboy-bin.000001
-rw-rw----. 1 mysql mysql 168 Feb  7 21:47 /application/mysql/data/oldboy-bin.000002
-rw-rw----. 1 mysql mysql  60 Feb  7 21:47 /application/mysql/data/oldboy-bin.index
-rw-rw----. 1 mysql mysql 120 Feb  7 21:47 /application/mysql/data/oldboy-bin.000003    ---新binlog
可以看到,使用-F參數后,每備份一次,都會重新生成新的binlog記錄數據
13. 記錄binlog位置的特殊參數(--master-data)

mysqldump里提供了一個參數,使得管理員不用刷新binlog,也可以找到全量和增量的臨界點,這就是“--master-data”參數。使用這個參數備份后,在備份的文件對應得SQL語句里會添加CHANGE MASTER語句及binlog文件及位置點信息。
當“--master-data=1”時,備份結果為可執行的“CHANGE MASTER...”語句;當“--master-data=2”時,備份結果為注釋的“--CHANGE MASTER...”語句,“--”在SQL語句里為注釋的意思。“--master-data”參數除了確定增量恢復和全備之間的臨界點之外,進行主從復制時的作用更大。

[root@oldboy ~]# mysqldump --master-data=1 oldboy --compact | head -1
CHANGE MASTER TO MASTER_LOG_FILE='oldboy-bin.000003', MASTER_LOG_POS=120;
[root@oldboy ~]# mysqldump --master-data=2 oldboy --compact | head -1
-- CHANGE MASTER TO MASTER_LOG_FILE='oldboy-bin.000003', MASTER_LOG_POS=120;
14. 鎖定所有表備份(-x參數)

默認情況下,在使用mysqldump命令備份期間,數據庫是可以寫入數據的,此時,備份的數據就不是某一個時刻的一致性備份了。如果備份時使用-x鎖表備份就會取得0點時刻的完整備份,即在0點時刻停止所有寫入操作,然后導出備份數據,備份完畢,放開寫入。

鎖表與不鎖表備份示意圖
15. innodb表特有的備份參數(--single-transaction)

當使用mysqldump的“--single-transaction”對innodb表進行備份時,會開啟一個事務,并將整個備份過程放到一個事務里,以確保執行本次dump會話時,不會看到其他連續會話已經提交了的數據,即備份開始時刻的數據是什么樣,備份出來就是什么樣。相當于是鎖表之后備份的數據,但是這個參數允許在備份期間寫入數據的,而不是在使用“-x”參數鎖表之后,備份期間無法寫入任何數據。

mysqldump -B --master-data=2 --single-transaction oldboy | gzip > /opt/all.sql.gz
--single-transaction備份原理示意圖

“--single-transaction”是innodb表的特有備份參數,只有事務型引擎,才能支持這樣得備份功能。

1.3 mysqldump重要關鍵參數說明

-B,--databases:會在備份的數據中增加建庫(create)及“use庫”的語句,可以直接接多個庫名,同時備份多個庫*
-A,--all-databases:備份所有的數據庫*
-d,--no-data:只備份庫表結構(SQL語句形式),沒有行數據
-t,--no-create-info:只備份表內行數據(SQL語句形式),沒有表結構
-T,--tab=name:將庫表和數據分離成不同的文件,行數據是純文本,表結構是SQL語句,5.6版本默認沒有權限操作,需要修改my.cnf參數
-F,--flush-logs:刷新binlog日志,生成binlog文件,將來增量恢復從這個新binlog文件開始,當備份多個庫時,每個庫都會刷新一次binlog,如果想只刷新一次binlog,可加“--lock-all-tables”或“--master-data”參數*
--master-data={1|2}:在備份結果中增加binlog日志文件名及對應的binlog位置點(即CHANGE MASTER...語句)。值為1時是不注釋狀態,值為2時是注釋狀態,該參數執行時會打開“--lock-all-tables”功能,除非有“--single-transaction”存在,使用該參數時會關閉“--lock-tables”功能*
-x,--lock-all-tables:備份時對所有數據庫的表執行全局讀鎖,期間同時禁止“--single-transaction”和“--lock-tables”參數功能*
-I,--lock-tables:鎖定所有的表為只讀
--single-transaction:在備份InnoDB引擎數據表時,通常會啟用該選項來獲取一個一致性的數據快照備份,它的工作原理是設定本次備份會話的隔離級別為REPEATABLE READ,并將整個備份放在一個事務里,以確保執行本次dump會話時,不會看到其他連續會話已經提交了數據,即備份開始時刻的數據是什么樣,備份出來就是什么樣子。相當于鎖表備份數據,但是這個參數是允許在備份期間寫入數據的,而不是-x鎖表后的備份期間無法寫入任何數據,啟用該參數會關閉“--lock-tables”*
-R,--routines:備份存儲過程和函數數據
--triggers:備份觸發器數據
--compact:只顯示很少的有用輸出,適合學習和測試環境調試用
提示:標*的參數為工作中比較重要的參數。

1.4 生產場景下,不同引擎的mysqldump備份命令

innodb引擎的備份命令:

mysqldump -A -B --master-data=2 --single-transaction | gzip > /opt/all.sql.gz    ---備份期間依然可以寫入數據

多引擎混合(比如myisam與innodb混合)的備份命令:

mysqldump -A -B --master-data=2 | gzip > /opt/all_$(date +%F).sql.gz    ---會鎖表

注意:如果數據庫用到了存儲過程和函數特殊功能,就加上“-R”備份,如果用到了觸發器功能則加上“--triggers”備份(--triggers選項默認開啟);如果考慮切割binlog日志也可以加“-F”;如果不想備份所有庫,也可以取消“-A”,獨立指定多個庫備份。

1.5 利用SQL語句方式對表進行導入導出

1. 導出表
mysql> use oldboy;
Database changed
mysql> select * from test;
+----+---------+
| id | name    |
+----+---------+
|  1 | oldboy  |
|  2 | oldgirl |
|  3 | inca    |
|  4 | zuma    |
|  5 | kaka    |
+----+---------+
5 rows in set (0.08 sec)
mysql> select * from test into outfile "/tmp/oldboy_test1.txt";    ---將oldboy庫里的test表導出為純文本
Query OK, 5 rows affected (0.03 sec)
mysql> system cat /tmp/oldboy_test1.txt
1   oldboy
2   oldgirl
3   inca
4   zuma
5   kaka

導出時設置字符集:

select * from test into outfile "/tmp/oldboy_test2.txt" character set utf8;

以指定的分隔符導出,這里指定“-”為分隔符:

mysql> select * from test into outfile "/tmp/oldboy_test3.txt" fields terminated by "-";
Query OK, 5 rows affected, 1 warning (0.00 sec)
mysql> system cat /tmp/oldboy_test3.txt
1-oldboy
2-oldgirl
3-inca
4-zuma
5-kaka

導出時設置對字段內容進行引用,使用雙引號:

mysql> select * from test into outfile "/tmp/oldboy_test4.txt" fields enclosed by '"';
Query OK, 5 rows affected (0.00 sec)
mysql> system cat /tmp/oldboy_test4.txt
"1" "oldboy"
"2" "oldgirl"
"3" "inca"
"4" "zuma"
"5" "kaka"
2. 導入表

先清空test表:

mysql> delete from test;
Query OK, 5 rows affected (0.14 sec)

將前面的oldboy_test1.txt格式的數據導入數據庫:

mysql> system cat /tmp/oldboy_test1.txt
1   oldboy
2   oldgirl
3   inca
4   zuma
5   kaka
mysql> load data infile '/tmp/oldboy_test1.txt' into table test;
Query OK, 5 rows affected (0.06 sec)
Records: 5  Deleted: 0  Skipped: 0  Warnings: 0
mysql> select * from test;
+----+---------+
| id | name    |
+----+---------+
|  1 | oldboy  |
|  2 | oldgirl |
|  3 | inca    |
|  4 | zuma    |
|  5 | kaka    |
+----+---------+
5 rows in set (0.00 sec)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容