二進制日誌簡介
mysql的二進制日誌從本質上來講就是重做日誌,它記錄了mysql服務器上此前所發生的所有引起了數據改變或潛在會影響數據改變的相關的操作。這個在恢復數據時非常有用,可以基於備份,通過二進制日誌文件將數據恢復至某一個具體的時間點。當然二進制日誌文件不能和數據文件放在同一塊磁盤上。
查看當前服務器的二進制日誌文件
MariaDB [(none)]> show binary logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 355 | | mysql-bin.000002 | 351 | +------------------+-----------+
當一個日誌文件的大小到達指定的大小後,日誌文件會自動滾動。若要手動滾動,可以使用flush logs。這個在備份的過程中經常用到。
MariaDB [(none)]> flush logs; Query OK, 0 rows affected (0.04 sec) MariaDB [(none)]> show binary logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 355 | | mysql-bin.000002 | 394 | | mysql-bin.000003 | 351 | +------------------+-----------+ 3 rows in set (0.00 sec)
顯示指定的二進制日誌文件中的相關事件
格式:SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
MariaDB [(none)]> show binlog events in 'mysql-bin.000003'\G ........ *************************** 7. row *************************** Log_name: mysql-bin.000003 Pos: 417 Event_type: Query Server_id: 1 End_log_pos: 544 Info: use `sakila`; insert into actor(first_name,last_name) values('baby','James') *************************** 8. row *************************** Log_name: mysql-bin.000003 Pos: 544 Event_type: Xid Server_id: 1 End_log_pos: 571 Info: COMMIT /* xid=16 */ .......
Log_name #日誌文件名
Pos #開始位置
Event_type #事件類型
Server_id #由哪一臺服務器產生
End_log_pos #結束位置
Info #日誌信息
只是這裏的日誌沒有時間,可以通過mysqlbinlog(客戶端命令)工具來更詳細地顯示日誌信息。
mysqlbinlog:
--start-position=# #從指定的事件位置查看
--stop-position=# #只顯示到指定的事件位置
--start-datetime=YYYY-MM-DD hh:mm:ss #從指定的時間查看
--stop-datetime=YYYY-MM-DD hh:mm:ss #只顯示到指定的時間
[root@CentOS-6 mysql_bin_log]# mysqlbinlog mysql-bin.000003 ...... # at 637 #150728 15:41:22 server id 1 end_log_pos 764 Query thread_id=5 exec_time=0 error_code=0 SET TIMESTAMP=1438069282/*!*/; insert into actor(first_name,last_name) values('Neal','James') /*!*/; # at 764 ..........
# at 637 #事件的開始位置(也是上一個事件的結束位置)
#150728 15:41:22 #事件發生的日期和時間
server id 1 #事件發生所在的服務器的標識
end_log_pos 764 #事件的結束位置
Query #事件的類型
thread_id=5 #事件發生時所在的服務器執行此事件的線程的ID
exec_time=0 #語句的時間戳與將其寫入二進制文件中的時間差
error_code=0 #錯誤代碼
事件內容:
SET TIMESTAMP=1438069282/*!*/;
insert into actor(first_name,last_name) values('Neal','James')
/*!*/;
# at 764 #下一個日誌的開始位置
日誌的記錄格式有3種:
1、基於“語句”記錄:statement
2、基於“行”記錄:row (用這個記錄數據更加精確)
3、“混合”模式 :mixed
相關的服務器變量:
MariaDB [(none)]> show global variables like '%binlog%'; +-----------------------------------+----------------------+ | Variable_name | Value | +-----------------------------------+----------------------+ ............... | binlog_cache_size | 32768 | #二進制日誌緩存大小 | binlog_format | MIXED | #二進制日誌記錄格式(MIXED.statement ,row) | binlog_stmt_cache_size | 32768 | | max_binlog_cache_size | 18446744073709547520 | | max_binlog_size | 1073741824 | #二進制日誌文件的單文件上限;達到這個大小了,會自動滾動 (單位字節) | max_binlog_stmt_cache_size | 18446744073709547520 | | sync_binlog | 0 | #設定多久將緩存中的數據同步至二進制日誌文件(磁盤上);0表示不同步(有內部線程控制);任何正值都表示記錄多少個語句後同步一次; +-----------------------------------+----------------------+ MariaDB [(none)]> show global variables like '%log_bin%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | log_bin | ON | #記二進制日誌文件存放位置及文件名 | sql_log_bin | ON | #是否啓用二進制日誌 +---------------------------------+-------+
log_bin往往在配置文件中指定,如果指定了其他的存放目錄,需要將該目錄的屬主和數組改成mysql,否則數據庫無法啓動。
在備份和恢復的過程中往往還需要查看數據庫當前所記錄的二進制日誌文件以及當前事件所處的位置,
MariaDB [(none)]> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000003 | 791 | | | +------------------+----------+--------------+------------------+
如果備份文件只備份了某個事件之前的所有數據(在備份時往往會記錄這個事件的位置,簡單起見,也可以直接滾動日誌),那麼後面所做的操作都需要通過二進制日誌文件來恢復。通過--start-position指定備份結束的事件位置,--stop-position指定需要恢復到哪個事件。
[root@CentOS-6 mysql_bin_log]# mysqlbinlog --start-position=num1 --stop-position=num2 mysql-bin.###### > /tmp/a.sql [root@CentOS-6 mysql_bin_log]# mysql < /tmp/a.sql
當然,備份文件的事件結束位置和需要恢復至某個事件的位置之間可能隔了很多個日誌文件,將它們全部導出,再導入至服務器執行一次即可。這個也可以通過--start-datetime,--stop-datetime來實現。
mysqldump備份恢復
mysqldump是一個客戶端工具,通過mysql協議連接至數據庫服務器,並將獲取的數據結果轉化爲DDL,DML語句保存下來。備份的機制比較簡單,但是如果數據庫中的數據很多,mysqldump產生的SQL語句就會非常龐大,使得恢復的速度非常慢。mysqldump支持MyISAM表的溫備,對InnoDB支持到熱備。
爲了操作的方便可以在家目錄下的.my.cnf文件中添加[mysqldump]或[client],將數據庫管理員的用戶名密碼寫在下面即可。如下:
[client] user = root password = ###### host = localhost
mysqldump常用選項:
-u,-h,-p #指定連接數據庫的用戶名密碼,地址
-A, --all-databases #備份所有數據庫
-x, --lock-all-tables #鎖定所有表
-l, --lock-tables #鎖定備份的表(只有備份單張表才建議使用這個選項)
-B, --databases db_name1 db_name2 ... #備份指定的數據庫
--single-transaction #啓動一個大的單一事務實現備份(熱備,只能針對InnoDB存儲引擎來實現,如果備份的表
#中有MyISAM的表,則對於這些表沒有任何意義)
-C, --compress #壓縮傳輸(在服務器端會佔用更過的cup時鐘週期)
-E, --events #備份指定庫的事件調度器;
-R, --routines #備份存儲過程和存儲函數;
--triggers #備份觸發器
-F,--flush-logs #鎖定表之後執行flush logs命令(日誌滾動);
--master-data[=num] #在完全備份的備份文件中記錄下來,在備份那一時刻(鎖定所有表時),對應的二進制日
#志文件的文件名及其位置。num=0表示不記錄,num=1,記錄CHANGE MASTER TO語
#句(語句未被註釋),num=2,記錄爲註釋語句;
mysqldump備份過程
1、對所有表進行鎖定,然後備份所有庫。
[root@CentOS-6 data]# mysqldump --all-databases --lock-all-tables --master-data=2 > /backup/`date +%F`.all.sql
2、數據庫更改之後,通過二進制日誌文件對其進行增量備份。增量備份前先查看完全備份文件中記錄的事件位置(--master-data),然後查看當前的事件位置,備份兩個事件之間的所有事件。這裏沒有進行日誌滾動,簡單起見,可以直接在執行完全備份時加上--flush-logs,自動實現日誌滾動。
[root@CentOS-6 backup]# vim 2015-07-28.all.sql ..... -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1093; .... #備份時事件點 MariaDB [hellodb]> show master status; #當前事件點 +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000003 | 9677 | | | +------------------+----------+--------------+------------------+ [root@CentOS-6 data]# mysqlbinlog --start-position=1093 --stop-position=9677 /data/mysql_bin_log/mysql-bin.000003 > /backupup/`date +%F`.inc.sql
以上的備份是溫備,備份過程中需要對錶進行鎖定,數據無法進行更改。如果需要熱備,加上--single-transaction即可,當然鎖定表就不需要了(--lock-all-tables)。
mysqldump恢復過程
1、在恢復過程中,也會產生大量的二進制日誌,這些日誌沒有什麼用,可以在恢復開始之前將數據庫上的二進制日誌功能關閉。
MariaDB [(none)]> set sql_log_bin=0; Query OK, 0 rows affected (0.00 sec)
2、在最後一次增量備份之後與數據庫崩潰之前的這段時間內,數據的變化沒有備份,這段時間內的數據變化信息需要通過二進制日誌文件獲取,所以在數據庫崩潰之後,首先要保護其二進制日誌文件。假設數據庫崩潰之前的最後一個事件位置爲10510。(這段時間內產生的二進制日誌文件可能有很多個,除了最後一個日誌文件,其餘的一一導出即可,最後一個日誌文件導出至某一個事件位置之前)
[root@CentOS-6 data]# mysqlbinlog --start-position=9677 --stop-position=10510 /data/mysql_bin_log/mysql-bin.000003 > /backup/`date +%F`.inc2.sql
3、導入備份的數據。
[root@CentOS-6 backup]# mysql < 2015-07-28.all.sql [root@CentOS-6 backup]# mysql < 2015-07-28.inc.sql [root@CentOS-6 backup]# mysql < 2015-07-28.inc2.sql
mysqldump部分備份
mysqldump [OPTIONS] database [tables]:備份一個或多個表
mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]:備份一個或多個庫
備份恢復單個表
[root@CentOS-6 backup]# mysqldump hellodb students --single-transaction --master-data=2 > /backup/students.sql; ##### [root@CentOS-6 backup]# vim students.sql ..... use hellodb; #在還原表前,在備份文件開頭添加使用的數據庫 ###### [root@CentOS-6 backup]# mysql < students.sql # 恢復表
備份多個表或庫,與此類似,只是通過二進制日誌恢復時,需要在二進制日誌文件中篩選出僅針對某一個表或者庫的操作,然後在導出,恢復。在實現部分備份時,要確保備份的數據中所有的InnoDB表都需要存放爲單個表空間(每表單獨表空間),不然只能備份所有庫。
lvm2快照備份
lvm2屬於幾乎熱備,在快照的那一刻,需要對全表進行鎖定,快照完成之後立刻釋放鎖。
備份過程
1、鎖定所有表
MariaDB [hellodb]> flush tables with read lock; Query OK, 0 rows affected (0.00 sec)
2、記錄當前的事件位置,也可以直接滾動日誌
MariaDB [(none)]> show master status ; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000005 | 365 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
3、創建快照(前提是數據庫的數據目錄必須放在邏輯捲上)
[root@CentOS-6 mysql_bin_log]# lvcreate -L 2G -s -p r -n dataBackup /dev/babyVG/babyLV Logical volume "dataBackup" created
4、解鎖所有表
MariaDB [(none)]> unlock tables; Query OK, 0 rows affected (0.00 sec)
5、掛載快照,複製快照中的數據至備份目錄。然後刪除快照
[root@CentOS-6 backup]# mount /dev/babyVG/dataBackup /backup/snapshot/ mount: block device /dev/mapper/babyVG-dataBackup is write-protected, mounting read-only [root@CentOS-6 backup]# cp -a /backup/snapshot/* /backup/lvmbackup/ [root@CentOS-6 backup]# lvremove /dev/babyVG/dataBackup Logical volume babyVG/dataBackup contains a filesystem in use.
還原:(服務關閉狀態下)
1、備份之後的數據變化通過日誌導出
[root@CentOS-6 mysql_bin_log]# mysqlbinlog --start-position=365 --stop-position=1183 mysql-bin.000005 > /tmp/a.sql;
2、複製備份數據至數據目錄,修改權限
[root@CentOS-6 mysql]# cp -a /backup/lvmbackup/* ./ [root@CentOS-6 mysql]# chown -R mysql:mysql ./*
3、啓動服務,導入數據
[root@CentOS-6 mysql]# service mysqld start Starting MySQL. [ OK ] [root@CentOS-6 mysql]# mysql < /tmp/a.sql
Xtrabackup備份恢復
Xtrabackup是由percona提供的mysql數據庫備份工具,是一個開源的工具,能夠對innodb和xtradb數據庫進行熱備和增量備份,對於MyISAM,僅支持到溫備,對MyISAM使用增量備份時,其實是完全備份。Xtrabackup使用簡單,功能強大。Xtrabackup具備的特點:(1)備份過程快速、可靠;(2)備份過程不會打斷正在執行的事務;(3)能夠基於壓縮等功能節約磁盤空間和流量;(4)自動實現備份檢驗;(5)還原速度快;
可從官網上下載到最新版本(http://www.percona.com/software/percona-xtrabackup/ ),直接下載對應的rpm包即可。下載到本地之後使用yum安裝(yum install xxx.rmp),會自動解決依賴關係。
完全備份
1、首先創建一個專門用於備份用戶(最小權限)
MariaDB [hellodb]> create user 'bkpuser'@'localhost' identified by 'bkpuser'; Query OK, 0 rows affected (0.00 sec) MariaDB [hellodb]> grant reload,lock tables,process,replication client on *.* to 'bkpuser'@localhost; Query OK, 0 rows affected (0.00 sec) MariaDB [hellodb]> flush privileges; Query OK, 0 rows affected (0.00 sec)
2、備份數據,--no-timestamp選項來阻止命令自動創建一個以時間命名的目錄,此時需要自行命名目錄。/back/whole.back即爲備份的存放路徑。
[root@CentOS-6 ~]# innobackupex --user=bkpuser --password=bkpuser --no-timestamp /backup/whole.back ....... 150728 21:01:15 innobackupex: Connection to database server closed 150728 21:01:15 innobackupex: completed OK!
在使用innobakupex備份時,其會調用xtrabackup來實現備份,備份還包括觸發器和數據庫配置信息相關的文件。
下面是備份的存放目錄。
[root@CentOS-6 whole.back]# ll total 178216 -rw-r--r--. 1 root root 358 Jul 28 21:19 backup-my.cnf drwxr-x---. 2 root root 4096 Jul 28 21:45 hellodb -rw-r-----. 1 root root 79691776 Jul 28 21:45 ibdata1 -rw-r--r--. 1 root root 50331648 Jul 28 21:45 ib_logfile0 -rw-r--r--. 1 root root 50331648 Jul 28 21:45 ib_logfile1 drwx------. 2 root root 4096 Jul 28 21:45 mysql drwxr-xr-x. 2 root root 4096 Jul 28 21:19 performance_schema drwxr-x---. 2 root root 4096 Jul 28 21:45 sakila drwxr-xr-x. 2 root root 4096 Jul 28 21:19 test -rw-r--r--. 1 root root 33 Jul 28 21:38 xtrabackup_binlog_info -rw-r--r--. 1 root root 45 Jul 28 21:45 xtrabackup_binlog_pos_innodb -rw-r-----. 1 root root 91 Jul 28 21:45 xtrabackup_checkpoints -rw-r--r--. 1 root root 662 Jul 28 21:38 xtrabackup_info -rw-r-----. 1 root root 2097152 Jul 28 21:28 xtrabackup_logfile
xtrabackup_checkpoints #備份類型(如完全或增量)、備份狀態(如是否已經爲prepared狀態)和LSN(日誌序
#列號)範圍信息;
xtrabackup_binlog_info #mysql服務器當前正在使用的二進制日誌文件及至備份這一刻爲止二進制日志事件的
#位置。
backup-my.cnf # 備份命令用到的配置選項信息
xtrabackup-info #mysql服務器的屬性設定信息
xtrabackup_logfile #xtrabackup的日誌文件
恢復過程
在備份完成後,數據還不能直接用於恢復,因爲在備份的數據中可能會包含未提交的事務或已經提交但尚未同步至數據文件中的事務。通過-apply-log選項可以實現對未提交的事務進行回滾,同步已經提交的事務至數據文件,使得數據文件處於一致性狀態。在這個過程中還可以使用--use-memory選項來設置其可以使用的內存大小(默認100M),以加快其速度。當看到completed OK!,說明上述的事件已經完成,數據已經可以用於恢復。
1、準備一個完全備份
[root@CentOS-6 backup]# innobackupex --apply-log /backup/whole.back/ ...... 150728 21:07:56 innobackupex: completed OK!
2、通過--copy-back將數據複製到數據庫的數據目錄下。
[root@CentOS-6 backup]# innobackupex --copy-back /backup/whole.back/ ...... 150728 21:09:48 innobackupex: completed OK!
3、注意屬組屬主的修改,不然無法啓動mysql。
[root@CentOS-6 mysql]# chown -R mysql:mysql /data/mysql [root@CentOS-6 mysql]# service mysqld start Starting MySQL. [ OK ]
在恢復的整個過程中,mysql服務不需要啓動。xtrabackup的恢復不包括二進制日誌文件的恢復。
Xtrabackup增量備份
使用--incremental選項指定這是一個增量備份過程,通過--incremental-basedir指定這個增量備份是基於哪個完全備份。如果不是第一次增量備份,--incremental-basedir應該指向上一次的增量備份。完成之後會有一個獨立的備份文件。
備份過程
1、完全備份
[root@CentOS-6 ~]# innobackupex --user=bkpuser --password=bkpuser --no-timestamp /backup/whole.back ..... 150728 21:19:55 innobackupex: completed OK!
2、第一次增量備份
[root@CentOS-6 ~]# innobackupex --no-timestamp --incremental /backup/inc.1.back --incremental-basedir=/backup/whole.back/ ...... 150728 21:22:36 innobackupex: completed OK!
3、第二次增量備份
[root@CentOS-6 ~]# innobackupex --no-timestamp --incremental /backup/inc.2.back --incremental-basedir=/backup/inc.1.back/ ....... 150728 21:24:48 innobackupex: completed OK!
增量備份的恢復
--redo-only表示僅提交已完成的事務,而不回滾未提交的事務,因爲未提交的事務可能在增量備份中提交,將增量備份合併至完全備份後,恢復即可。
1、合併所有的增量備份至完全備份。最後一個增量備份合併時可以不加--redo-only選項。
[root@CentOS-6 ~]# innobackupex --apply-log --redo-only /backup/whole.back/ ...... 150728 21:28:47 innobackupex: completed OK! [root@CentOS-6 ~]# innobackupex --apply-log --redo-only /backup/whole.back/ --incremental-dir=/backup/inc.1.back/ ...... 150728 21:37:48 innobackupex: completed OK! [root@CentOS-6 ~]# innobackupex --apply-log --redo-only /backup/whole.back/ --incremental-dir=/backup/inc.2.back/ ....... 150728 21:38:48 innobackupex: completed OK!
2、複製到數據庫的數據目錄下。
[root@CentOS-6 ~]# innobackupex --copy-back /backup/whole.back/ [root@CentOS-6 ~]# chown -R mysql:mysql /data/mysql [root@CentOS-6 ~]# service mysqld start Starting MySQL.... [ OK ]
單張表的導入導出
MyISAM表可以通過直接複製文件的方式,實現單張表在MySQL服務器之間的轉移,InnoDB表無法通過此方式來實現轉移。xtrabackup工具可以幫助實現此功能(前提是InnoDB表的表空間單獨存放)。
1、這個需要在數據文件處於一致性狀態下,通過--export選項將某表導出(所有的表)
[root@CentOS-6 ~]# innobackupex --apply-log --export /backup/whole.back/ ........ 150728 21:45:08 innobackupex: completed OK!
2、在目標服務器上創建一個跟原表表結構完全一致的表。
MariaDB [hellodb]> CREATE TABLE mytable (...) ENGINE=InnoDB;
3、刪除此表的表空間
MariaDB [hellodb]> alter table database.tableName discard tablespace;
4、從“導出”表的服務器上,複製該表的table.ibd和table.exp文件至目標服務器的數據目錄中(複製過來的文件屬組屬主都應該是mysql)
[root@CentOS-6 hellodb]# cp -a students.ibd students.exp /data/mysql/hellodb/ [root@CentOS-6 hellodb]# cd /data/mysql/hellodb/ [root@CentOS-6 hellodb]# chown mysql:mysql students.ibd students.exp
5、導入表空間
MariaDB [hellodb]> alter table students import tablespace;
恢復完成.................^_^