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文件數據一條不多(不能和全備的內容重合),一條不少(全備后的所有數據都要有)。
(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”是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)