數據庫很重要,沒有備份,數據丟失只能跑路。所以還是做好備份吧!
一、工具介紹
mysqldump是mysql自帶的邏輯備份工具。
它的備份原理是,通過協議連接到mysql數據庫,將需要備份的數據查詢出來,將查詢出的數據轉換成對應的insert語句,當我們需要還原這些數據時,只要執行這些insert語句,即可將對應的數據還原。
二、工具特點
- 免費備份工具
- 支持遠程備份
- 支持生成CSV格式或XML格式的文件
- 可以使用文本工具直接處理對應的備份數據,以更靈活便利的進行恢復工作
- 與存儲引擎無關,可以在多種存儲引擎下進行備份恢復,對innodb引擎支持熱備,對MyISAM引擎支持溫備(施加表鎖)
- 當數據為浮點類型時,會出現精度丟失
- 備份的過程是串行化的,不支持並行備份
三、備份權限
備份對象 | 權限 |
---|---|
table | SELECT |
view | SHOW VIEW |
trigger | TRIGGER |
event | EVENT |
儲存過程、函數 | SELECT mysql.proc |
轉儲用戶 | SELECT "mysql"系統庫 |
備份未使用--single-transaction選項時,還需要LOCK TABLES權限
四、工具使用限制
-
mysqldump轉儲時默認不會備份INFORMATION_SCHEMA, performance_schema, sys,如有需求轉儲,需要再命令行上顯式的指定他們。
-
mysqldump不會轉儲InnoDB CREATE TABLESPACE語句。
-
mysqldump不會備份 NDB cluster ndbinfo信息數據庫。
-
在啟用了GTID的數據庫中使用mysqldump備份時需要注意,如果備份文件中包含了GTID信息,則無法恢復到沒有啟用GTID的數據庫中。
-
Windows通過PowerShell使用如下命令進行轉儲時,轉儲文件默認使用UTF-16編碼,而MySQL不允許將UTF-16作為連接字符集,所以通過如下命令備份的轉儲文件將無法正確加載到數據庫中
mysqldump [options] > dump.sql
-
mysqldump是單線程,當數據量大時備份時間長,甚至有可能在備份過程中非事務表長期鎖表對業務造成影響(SQL形式的備份數據恢復時間也較長)。
-
慎用 --compact 參數,此參數會去掉文件頭與文件尾的一些參數設置(比如時區,字符集...),導致隱患。
-
參數 --lock-all-tables,--flush-privileges分別會在備份時進行 flush tables 和 flush privileges 操作,會產生GTID,備份從庫時請注意。
-
在對數據庫進行完全備份前,需要收集數據庫相關信息(存儲引擎、字符集等),確保備份內容完整,以下為收集語句:
-- 查看表相關信息 select table_schema,table_name,table_collation,engine,table_rows from information_schema.tables where table_schema NOT IN ('information_schema' , 'sys', 'mysql', 'performance_schema'); -- 查看是否存在存儲過程、觸發器、調度事件等 select count(*) from information_schema.events; select count(*) from information_schema.routines; select count(*) from information_schema.triggers; -- 查看字符集信息 show variables like 'character%';
-
mysqldump的一些選項跟mysqlpump有些變化,在使用中需注意:
mysqldump | mysqlpump |
---|---|
--routines、--events的別名分別為-R、-E | --routines、--events不存在別名 |
存在master-data選項 | 不存在master-data選項,在進行構建主從需要通過master_auto_position來控制,不能夠直觀的通過指定binlog以及position來構建主從 |
-d的別名是--no-data | -d的別名是--skip-dump-rows |
轉儲文件默認帶DROP TABLE語句 | 轉儲文件默認不帶DROP TABLE、DROP USER(在使用--users備份用戶時)語句,導入時可能會因為用戶存在或者表存在而報錯 |
備份不指定數據庫或者-A會提示報錯 | 備份不指定數據庫或者-A,默認備份所有的數據。ps:除了INFORMATION_SCHEMA, performance_schema, ndbinfo, or sys |
五、已知BUG
MySQL5.7.7至今(2020/11/02)的所有5.7的小版本,在使用mysqldump在執行--all-databases都會清空mysql.proc導致sys無法正常使用。
mysql> SELECT * FROM sys.processlist;
ERROR 1356 (HY000): View 'sys.processlist' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
在使用mysqldump在執行--all-databases不會備份mysql.proc下的系統自身的存儲過程,導致導入到新機器后,部分sys下的視圖沒法正常使用;這是一個BUG,並且只存在於MySQL5.7。
bug連接:
如果因為使用--all-databases參數已經造成sys異常報錯,這樣做可以修復其異常:
mysql_upgrade --upgrade-system-tables --skip-verbose --force
-- 使用mysql_upgrade的時候要加上 --upgrade-system-tables。不然會掃描用戶庫表,期間加鎖且速度一般。
六、備份前注意事項
6.1 需要長時間備份或導入時,請使用 screen 窗口工具
如果你正在做一個大表 DDL 或者批量執行一個 sql 文件,執行一半遠程連接斷開了,你會不會想吐血?如果剛好執行批量 sql 時沒有開啟事務,想想后果會怎樣?
使用 screen 時,即使當前遠程終端被斷開連接,也不會中斷正在執行的任務:
## 安裝 screen
yum install -y screen
## 開啟一個 screen
screen
## 查看所有開啟的 screen
screen -ls
## 重新連接到指定的 screen
screen -r xxx
6.2 檢查數據庫參數
參數 | 原因 |
---|---|
lock_wait_timeout | 默認值為1年,如果沒有修改默認設置,或者當前值是個挺長的時間,當mysqldump遇到長事務並在獲取lock超時時,mysqldump不會退出,會等待獲取MDL鎖。此時界面無任何輸出,使用者不進入數據庫查看,不會感知備份停滯等待,影響備份工作進度 |
6.3 檢查數據庫角色
檢查mysqldump備份角色,注意如果在從庫使用下面mysqldump命令時,不要將--master-data和--flush-logs一起使用,有可能造成數據庫死鎖影響備份與復制。
7、使用方法舉例
7.1 全庫備份
注意不僅需要備份數據,還需要備份存儲過程、觸發器、事件:
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --hex-blob --triggers --routines --events --all-databases > /tmp/backup/all_db_with_data.sql
注意:如果是MySQL5.7版本有BUG(詳情請看五、已知BUG)需要多添加一步操作:
進行mysql.proc 單表導出:
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --set-gtid-purged=off --hex-blob --triggers --routines --events --tables mysql proc > /tmp/backup/mysql_proc.sql
以上導出的SQL,必須在開啟SET @@SESSION.SQL_LOG_BIN= 0;
的情況下,利用mysql> source mysql_proc.sql
的方式導入,否則會造成異常情況影響主從建立,如果不是為了創建主從,可忽略此導入方式。
進行mysql.proc 單表導入:
#不搭建主從復制的情況下:
多種導入方式都可
#要搭建主從復制的情況下:
mysql> use mysql
mysql> SET @@SESSION.SQL_LOG_BIN= 0;
mysql> source /tmp/backup/mysql_proc.sql
7.2 單庫備份
## 備份表結構和數據
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --set-gtid-purged=off --hex-blob --databases employees > /tmp/backup/employees_all.sql
## 只備份表結構
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --set-gtid-purged=off --hex-blob --no-data --databases employees > /tmp/backup/employees_schema.sql
## 只備份數據
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --set-gtid-purged=off --hex-blob --no-create-info --databases employees > /tmp/backup/employees_only_data.sql
7.3 單表備份
## 只備份employees數據庫中的salaries表
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --set-gtid-purged=off --hex-blob --tables employees salaries > /tmp/backup/employees_salaries.sql
## 排除指定數據庫的指定表
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs --set-gtid-purged=off --hex-blob --ignore-table=employees.departments --ignore-table=employees.employees employees > /tmp/backup/employees_exclude_departments.sql
注意
如果備份時要排除某個數據庫中多個表,要使用多個--ignore-table語句,不能在后面加逗號做分割。
7.4 生成單獨的數據文件(-T)
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 --flush-logs -T /tmp/salaries --databases employees --tables salaries > employees_salaries.sql
注意事項
- 該選項值指定的是生成表備份文件的目錄。所以要如上所示添加--database --tables。該選項與--database、--all-databases選項互斥,不能一起使用
- 只有當mysqldump與mysqld服務器在同一台機器上運行時,才能使用該選項
因為在生成備份文件時只能使用本地目錄,並且執行備份的MySQL賬戶還必須具有FILE權限。所以, secure_file_priv系統參數必須設置為空串(因為是調用 SELECT ...INTO OUTFILE語句),以使得啟動mysqld進程的系統登錄賬戶可以將這些備份文件生成到指定的文件系統目錄下 - (注意,使用該選項時指定的目錄必須是備 份服務器上的目錄,不能遠程連接備份,因為SELECT ... INTO OUTIFLE 只能寫到服務器本地目錄下且啟動 mysqld 進程的用戶需要具有訪問權限
生成文件示例:
less salaries/salaries.txt
10001 60117 1986-06-26 1987-06-26
10001 62102 1987-06-26 1988-06-25
10001 66074 1988-06-25 1989-06-25
10001 66596 1989-06-25 1990-06-25
10001 66961 1990-06-25 1991-06-25
7.5 根據條件備份(-w)
只轉儲由給定的WHERE條件選擇的行
###按照where條件,備份指定庫下的指定表的數據
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 -w 'id > 10 and id < 20' --databases testdb --tables sbtest1 > /tmp/backup/sbtest1.sql
###按照where條件,備份指定庫下的所有表的數據
mysqldump -uops -p -h127.0.0.1 -P4444 --default-character-set=utf8mb4 --single-transaction --master-data=2 -w 'id > 10 and id < 20' --databases testdb > /tmp/backup/sbtest1.sql
注意事項
- 只用--database不用--table的情況下需注意:
同一個庫要所有的表都要有where條件列並且列數據類型一致。經測試同一個庫下如果有一個表不具有where條件列,此時mysqldump會報錯;經測試同一個庫下如果有表,具有同名where條件列,但數據類型不同,此時mysqldump不會報錯,但備份不出其數據,只會備份符合where條件的表的數據。 - 當只指定--tables而不指定--databases選項,或者在命令行選項中沒有給出表示庫名的參數時,mysqldump會把緊跟在--tables之后的命令行參數中的第一個當作庫名來解析,從第二個參數開始全部被解析為表名。
- 如果多次指定一個備份對象,則不會去重,而是執行多次備份.所以,在生產環境中不建議庫名與表名相同。
八、數據導入
8.1 備份導入前注意事項
(1) 在備份導入前要檢查以下參數的配置
參數 | 建議 | 原因 | 命令 |
---|---|---|---|
autocommit | 建議開啟 | 如果關閉,可能會造成導入語句無法自動提交,可能會導致事務卡住、事務回滾、binlog大事務,甚至數據庫關閉。 | set session autocommit = 1; |
wait_timeout \ interactive_timeout | 建議調大 | 設置過小,且導入時間長,會導致還沒導入完,會話超時斷開連接,導致任務失敗。 | set session wait_timeout=28800; \ set session interactive_timeout=28800; |
(2) 檢查SQL文件中所要DROP 的表是否是自己預期內的
less all_db_with_data.sql | grep -E "^DROP TABLE IF EXISTS|^USE"
8.2 使用PV工具監控文件導入過程
在一般的備份文件導入中,只能憑經驗去估測一下備份文件實際導入的時間,這里可以使用PV工具,較為精確的算出導數剩余量及完成時間,所以建議使用此種方式,進行數據導入
#參數說明:
#-W:在需要密碼輸入時有用,可等待密碼輸出完成,再開啟監控進度條
#-L:限流,將傳輸限制在每秒最大字節的范圍內(大小可自定義,單位可變)
shell> pv -W -L 2M all_db_with_data.sql | /data/mysql/base/5.7.25/bin/mysql -uops -p -S/data/mysql/data/3333/mysqld.sock
Enter password:
588MiB 0:04:54 [ 2MiB/s] [======================================================>] 100%
8.3 mysql client+PV+會話參數導入(推薦)
#參數說明:
#reset master:在導入機器有自身的GTID時,會導入失敗,所以可根據需要在echo里面添加"reset master"命令,清空GTID purge。
shell> (echo 'set @@autocommit=1; set @@interactive_timeout=28800; reset master;'; pv -W -L 5M all_db_with_data.sql) | mysql -h127.0.0.1 -P3333 -uops -p
shell> (echo 'set @@autocommit=1; set @@interactive_timeout=28800;'; pv -W -L 5M employees_all.sql) | mysql -h127.0.0.1 -P3333 -uops -p employees
九、特殊問題規范
9.1 場景1:
防止SQL導入中產生過大的binlog,使主從延遲增加,想在導入時把日志格式改為statement,減小binlog
涉及參數:
transaction_isolation
binlog_format
注意問題:
如果表是InnoDB表,並且事務隔離級別是READ COMMITTED或READ UNCOMMITTED,那么只能使用基於行的日志記錄。可以將日志格式改為statement,但在運行時這樣做會導致錯誤,因為InnoDB表不能再執行insert語句。
mysql> select @@binlog_format;
+-----------------+
| @@binlog_format |
+-----------------+
| STATEMENT |
+-----------------+
1 row in set (0.00 sec)
mysql> show variables like '%iso%';
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
| tx_isolation | READ-COMMITTED |
+-----------------------+----------------+
2 rows in set (0.00 sec)
mysql> create table test(id int, name varchar(20));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into test values(1, 'zhou'),(2, 'wei');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test;
+------+------+
| id | name |
+------+------+
| 1 | zhou |
| 2 | wei |
+------+------+
2 rows in set (0.00 sec)
mysql> insert into test values(3,'bing');
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
在執行備份導入時有將binlog_format臨時設置為statement需求時,需要檢查transaction_isolation是否為RR。在RC級別下,binlog_format設置為statement會導致不能進行insert相關操作。所以不是RR級別,請不要將binlog_format改為statement。
9.2 場景2:
備份或導入SQL包過大,超過max_allowed_packet,備份或導入失敗
涉及參數:
max_allowed_packet
注意問題:
備份或導入時確定數據庫表中的字符類型:如果有BLOB列或長字符串等字符類型建議合理增加這個值。
# mysqldump -h10.100.143.62 -umeslogin -P3306 -p --default-character-set=utf8mb4 --master-data=2 --flush-logs --single-transaction --set-gtid-purged=off --hex-blob --databases yfmes_metal_sys > yfmes_metal_sys_all.sql
mysqldump: Error 2020: Got packet bigger than 'max_allowed_packet' bytes when dumping table `operlog` at row: 264227
導入時也相似的原理。
可以在mysql、mysqldump等client命令后臨時修改此參數:
mysqldump [xxxx] --max_allowed_packet=256M > dump.sql
mysql [xxxx] --max_allowed_packet=256M < dump.sql