mysqldump 邏輯備份的正確姿式

在上一篇文章 MySQL 命令行工具之 mysqldump 深刻研究 中,咱們搞定了mysqldump的參數和基本原理。那麼咱們該怎麼樣最好的使用它的?它有哪些坑呢?html

1. 利用mysqldump進行邏輯備份mysql

1)全邏輯備份:linux

mysqldump -uxxx -p --flush-logs --delete-master-logs --all-databases > alldb.sql (天天晚上進行一次全備)
web

2)增量備份:sql

mysqladmin flush-logs (每小時刷一下,保存起來,進行了一次增量備份)數據庫

3)缺點:bootstrap

1> --all-databases 包含了 mysql 數據庫,其中包含了權限的數據,因此咱們應該加上 --flush-privileges,在恢復時,權限才能生效;安全

     注意 --all-databases 包括了mysql數據庫,可是不會包含 information_schema和performance_schema兩個數據庫。服務器

2> 由於 mysqldump 默認啓用了 --lock-tables,因此會致使在備份期間對全部表持有讀鎖: lock table tb read local,因此全部的update,delete語句less

     會被阻塞。可是select語句和insert語句不會被阻塞。

3> --delete-master-logs 備份以後,會執行 purge logs to 語句。刪除了備份以後的master上的binary log. 通常而言,咱們不建議隨便刪除binary log.

     咱們應該將它們保存起來,而不是直接刪除。以防萬一,要留條退路。

4> 該備份方式,雖然在整個備份過程當中持有了 lock table tb read local,可是仍是能夠執行 insert 語句的。因此獲得的不是一致性的備份。雖然獲得的不是

     一致性的備份,可是由於flush log以後,全部的操做 也會記入新的binary log,因此若是使用了全部新的binary log來進行徹底恢復的話,最後恢復的數據

     也是一致性的。固然不一致性的備份沒法用於搭建slave。

     若是要獲得一致性的備份的話,須要使用 --lock-all-tables 或者使用 --single-transaction 選項。前者使用了全局讀鎖,不容許任何修改操做。後者使用

     了事務的特性來獲得一致性備份。

因此咱們應該對上面的備份方式進行改良。

2. 使用mysqldump備份的最佳姿式

1)優化鎖 和 獲得一致性備份:

咱們可使用結合使用 --single-transaction 、--master-data=2 、--flush-logs 來達到將鎖定時間大大減小的目的。同時有獲得了一致性的備份,並且該一致性備份和 flush 的日誌也是一致的;

2)去掉 --delete-master-logs 選項,改成在備份以後,將全部被刷新的 binary log 移到一個地方保存起來;

3)由於使用了 --single-transaction 選項,針對的只能是 innodb 數據,可是mysql數據是Myisam引擎的,因此咱們最好將mysql數據庫的備份分開來,

     另外專門針對 mysql 數據庫進行一次操做。固然不分開來備份,可能也沒有問題。

4)還要加上 --routines 來備份存儲過程和函數,觸發器默認會備份。

優化以後,咱們獲得:

mysqldump -uxxx -p --single-transaction --master-data=2 --routines --flush-logs --databases db1 db2 db3 > alldb.sql;

mysqldump -uxxx -p --flush-privileges --databases mysql > mysql.sql;

若是將mysql也一塊兒備份的話:

mysqldump -uxxx -p --single-transaction --master-data=2 --routines --flush-logs --flush-privileges --all-databases > alldb.sql;

3. 使用mysqldump來搭建slave環境

搭建slave環境,通常有兩種方法,對於規模不大的庫,能夠採用mysqldump來搭建;對於規模很大的庫,最好採用xtrabackup來搭建,速度要快不少。

1)首先 分別在master和slave上設置不一樣的server_id=1/101,啓用master上的log-bin=1,啓用slave上的relog-log=relay-bin; 在master上設置:

     binlog_format=row;二進制日誌的格式。maser上最好還設置sync_binlog=1 和 innodb_flush_log_at_trx_commit=1防止發生服務器崩潰時

     致使複製破壞。在slave上最好還配置:read-only=1 和 skip-slave-start=1 前者能夠防止沒有super權限的用戶在slave上進行寫,後者防止在啓動

     slave數據庫時,自動啓動複製線程。之後須要手動start slave來啓動複製線程。注意slave沒有必要啓用 log-bin=1,除非須要搭建二級slave。

2)在master上創建一個具備複製權限的用戶:     

grant replication slave, replication client on *.* to repl@’192.168.%.%’ identified by123456’;

3)備份master上的數據庫,遷移到slave上:

[root@localhost ~]# mysqldump -uroot -p --routines --flush-logs --master-data=2 --databases db2 db1>/root/backup.sql
Enter password:
[root@localhost ~]# scp /root/backup.sql 192.168.137.9:/tmp/backup.sql
The authenticity of host '192.168.137.9 (192.168.137.9)' can't be established.
RSA key fingerprint is a4:cd:c0:13:d1:8c:c0:a5:e7:c4:43:b5:95:17:af:d3.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.137.9' (RSA) to the list of known hosts.
root@192.168.137.9's password:
backup.sql            

由於slave的搭建須要一致性的備份,因此須要啓用 --lock-all-tables(master-data=1/2會自動啓用--lock-all-tables)或者--single-transaction;

另外還須要知道該一致性備份的數據,對應的master上的binary log的文件名,以及在該文件中的position,因此必須啓用 master-data選項。

由於--master-data會啓用--lock-all-tables 因此數據纔是一致性的;可是致使了全局鎖,不能進行任何修改操做;下面咱們使用--single-transaction進行優化:

mysqldump -uroot -p --routines --flush-logs --single-transaction --master-data=2 --databases db1 db2 > /root/backup.sql; (--flush-logs非必須)

這樣全局鎖僅僅在備份的開始短暫的持有。不會再備份的整個過程當中持有全局鎖。

4)在slave上執行備份的腳本,而後連上master,開啓複製線程:

執行sql腳本:

mysql> source /tmp/backup.sql

找到 --master-data 輸出的 binary log 的文件名和postion:

[root@localhost ~]# head -50 /tmp/backup.sql

......
/*!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 */; -- -- Position to start replication or point-in-time recovery from -- -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000010', MASTER_LOG_POS=809;

執行 change master to, start slave:

在salve上執行命令開始複製:
mysql> change master to master_host='192.168.137.8', master_user='repl', master_password='123456',
    -> master_log_file='mysql-bin.000010', master_log_pos=809;
Query OK, 0 rows affected, 2 warnings (0.09 sec)

mysql> start slave;
Query OK, 0 rows affected (0.04 sec)

最後在slave上查看複製線程的狀態:

mysql> show slave status\G
... ...
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
......

slave_IO_Runing 和 slave_sql_runing 狀態都是yes表示搭建成功。

5)replication涉及到的三個線程
1> master上的 binlog dump(dump線程),即讀取master上的binlog,發送到slave上的線程。
2> slave上的IO線程:讀取slave上的relay log。
3> slave上的sql線程:執行IO線程讀取的relay log的線程。
                         

4. 使用mysqldump的備份進行 還原

下面使用 mysqldump 進行一個備份,而後刪除 datadir, 而後使用備份sql腳本和binary log進行還原的過程。

1)首先進行一個全備:

mysqldump -uroot -p --single-transaction --master-data=2 --routines --flush-logs --databases gs ngx_lua > gs_ngx_lua_backup.sql;

數據庫有兩個庫: gs , ngx_lua.

2)將 備份時刷新以後的 binary log 利用 mv 命令移動到安全的位置,也就是--master-data=2輸出的日誌文件,它以前的日誌文件都存儲到安全的位置:

[root@localhost ~]# head -n 50 gs_ngx_lua_backup.sql
-- MySQL dump 10.13  Distrib 5.6.26, for linux-glibc2.5 (i686)
--
-- Host: localhost    Database: gs
... ...--
-- Position to start replication or point-in-time recovery from
--

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000027', MASTER_LOG_POS=120;

也就是將 MASTER_LOG_FILE='mysql-bin.000027' 以前的日誌都存儲到其它位置。

而後執行:purge binary logs to 'mysql-bin.000027' 更新了 mysql-bin.index 中的索引信息,這裏並無刪除binary log,由於它們已經被mv走了

3)下面模擬一個 增量備份:

mysql> delete from user where id=5;
Query OK, 1 row affected (0.02 sec)

mysql> select * from user;
+----+----------+------+-------------+----------+
| id | name     | sex  | phone       | addr     |
+----+----------+------+-------------+----------+
|  1 | yuanfang |    1 | 14465463786 | hangzhou |
|  2 | Andy     |    0 | 14465463786 | beijing  |
|  3 | peter    |    0 | 14465463786 | Hongkong |
|  4 | lexin    |    1 | 36565634    | shenzhen |
+----+----------+------+-------------+----------+
4 rows in set (0.00 sec)
mysql> flush logs;
Query OK, 0 rows affected (0.11 sec)

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000027 |       370 |
| mysql-bin.000028 |       120 |
+------------------+-----------+
2 rows in set (0.00 sec)

這裏 flush logs 進行增量備份,而後將增量備份的 bianry log 文件 mysql-bin.000027 也存儲起來。

而後在進行一條 delete 語句:

mysql> select * from user;
+----+----------+------+-------------+----------+
| id | name     | sex  | phone       | addr     |
+----+----------+------+-------------+----------+
|  1 | yuanfang |    1 | 14465463786 | hangzhou |
|  2 | Andy     |    0 | 14465463786 | beijing  |
|  3 | peter    |    0 | 14465463786 | Hongkong |
+----+----------+------+-------------+----------+
3 rows in set (0.00 sec)

到這裏數據庫的最新狀態是:user 表只有3條記錄。

而後咱們一樣將 mysql-bin.000028 也存儲起來。

4)而後咱們刪除 data-dir 目錄中的全部文件,而後開始還原:

[root@localhost mysql]# pwd
/var/lib/mysql
[root@localhost mysql]# mv ./* /backup/before_delete/

此時 data-dir 目錄是空的。而後咱們試圖使用 mysqladmin -uroot -p shutdown 來關閉mysqld,發現早不到 mysql.sock 沒法關閉,咱們只好使用

killall mysqld

來關閉。

5)而後進行數據庫的初始化,而後開始還原

進入到 /usr/local/mysql/script 目錄,而後執行初始化:

./mysql_install_db  --user=mysql --datadir=/var/lib/mysql --basedir=/usr/local/mysql

[root@localhost scripts]# ./mysql_install_db  --user=mysql --datadir=/var/lib/mysql --basedir=/usr/local/mysql
Installing MySQL system tables...2015-10-24 16:45:19 0 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.6.26-log) starting as process 5870 .. .
2015-10-24 16:45:19 5870 [Note] InnoDB: Using mutexes to ref count buffer pool pages
2015-10-24 16:45:19 5870 [Note] InnoDB: The InnoDB memory heap is disabled
2015-10-24 16:45:19 5870 [Note] InnoDB: Mutexes and rw_locks use InnoDB's own implementation
2015-10-24 16:45:19 5870 [Note] InnoDB: Memory barrier is not used
2015-10-24 16:45:19 5870 [Note] InnoDB: Compressed tables use zlib 1.2.3
2015-10-24 16:45:19 5870 [Note] InnoDB: Using Linux native AIO
2015-10-24 16:45:19 5870 [Note] InnoDB: Not using CPU crc32 instructions
2015-10-24 16:45:19 5870 [Note] InnoDB: Initializing buffer pool, size = 6.0M
2015-10-24 16:45:19 5870 [Note] InnoDB: Completed initialization of buffer pool
2015-10-24 16:45:20 5870 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!
2015-10-24 16:45:20 5870 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB
2015-10-24 16:45:20 5870 [Note] InnoDB: Database physically writes the file full: wait...
2015-10-24 16:45:20 5870 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB
2015-10-24 16:45:21 5870 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB
2015-10-24 16:45:23 5870 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
2015-10-24 16:45:23 5870 [Warning] InnoDB: New log files created, LSN=45781
2015-10-24 16:45:23 5870 [Note] InnoDB: Doublewrite buffer not found: creating new
2015-10-24 16:45:23 5870 [Note] InnoDB: Doublewrite buffer created
2015-10-24 16:45:23 5870 [Note] InnoDB: 128 rollback segment(s) are active.
2015-10-24 16:45:23 5870 [Warning] InnoDB: Creating foreign key constraint system tables.
2015-10-24 16:45:23 5870 [Note] InnoDB: Foreign key constraint system tables created
2015-10-24 16:45:23 5870 [Note] InnoDB: Creating tablespace and datafile system tables.
2015-10-24 16:45:23 5870 [Note] InnoDB: Tablespace and datafile system tables created.
2015-10-24 16:45:23 5870 [Note] InnoDB: Waiting for purge to start
2015-10-24 16:45:23 5870 [Note] InnoDB: 5.6.26 started; log sequence number 0
2015-10-24 16:45:28 5870 [Note] Binlog end
2015-10-24 16:45:28 5870 [Note] InnoDB: FTS optimize thread exiting.
2015-10-24 16:45:28 5870 [Note] InnoDB: Starting shutdown...
2015-10-24 16:45:30 5870 [Note] InnoDB: Shutdown completed; log sequence number 1625977
OK

Filling help tables...2015-10-24 16:45:31 0 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.6.26-log) starting as process 5893 ...
2015-10-24 16:45:31 5893 [Note] InnoDB: Using mutexes to ref count buffer pool pages
2015-10-24 16:45:31 5893 [Note] InnoDB: The InnoDB memory heap is disabled
2015-10-24 16:45:31 5893 [Note] InnoDB: Mutexes and rw_locks use InnoDB's own implementation
2015-10-24 16:45:31 5893 [Note] InnoDB: Memory barrier is not used
2015-10-24 16:45:31 5893 [Note] InnoDB: Compressed tables use zlib 1.2.3
2015-10-24 16:45:31 5893 [Note] InnoDB: Using Linux native AIO
2015-10-24 16:45:31 5893 [Note] InnoDB: Not using CPU crc32 instructions
2015-10-24 16:45:31 5893 [Note] InnoDB: Initializing buffer pool, size = 6.0M
2015-10-24 16:45:31 5893 [Note] InnoDB: Completed initialization of buffer pool
2015-10-24 16:45:31 5893 [Note] InnoDB: Highest supported file format is Barracuda.
2015-10-24 16:45:32 5893 [Note] InnoDB: 128 rollback segment(s) are active.
2015-10-24 16:45:32 5893 [Note] InnoDB: Waiting for purge to start
2015-10-24 16:45:32 5893 [Note] InnoDB: 5.6.26 started; log sequence number 1625977
2015-10-24 16:45:34 5893 [Note] Binlog end
2015-10-24 16:45:34 5893 [Note] InnoDB: FTS optimize thread exiting.
2015-10-24 16:45:34 5893 [Note] InnoDB: Starting shutdown...
2015-10-24 16:45:35 5893 [Note] InnoDB: Shutdown completed; log sequence number 1625987
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

  /usr/local/mysql/bin/mysqladmin -u root password 'new-password'
  /usr/local/mysql/bin/mysqladmin -u root -h localhost.localdomain password 'new-password'

Alternatively you can run:

  /usr/local/mysql/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:

  cd . ; /usr/local/mysql/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl

  cd mysql-test ; perl mysql-test-run.pl

Please report any problems at http://bugs.mysql.com/

The latest information about MySQL is available on the web at

  http://www.mysql.com

Support MySQL by buying support/licenses at http://shop.mysql.com

WARNING: Found existing config file /usr/local/mysql/my.cnf on the system.
Because this file might be in use, it was not replaced,
but was used in bootstrap (unless you used --defaults-file)
and when you later start the server.
The new default config file was created as /usr/local/mysql/my-new.cnf,
please compare it with your file and take the changes you need.

WARNING: Default config file /etc/my.cnf exists on the system
This file will be read by default by the MySQL server
If you do not want to use this, either remove it, or use the
--defaults-file argument to mysqld_safe when starting the server

[root@localhost scripts]#
./mysql_install_db

初始化成功以後,執行:

/usr/local/mysql/bin/mysql_secure_installation

來進行密碼設置。這一步可能會報錯:找不到 /tmp/mysql.sock 文,解決方法,在/etc/my.cnf 中的[client], [mysql], [mysqld] 都進行下面的設置:

socket=/tmp/mysql.sock

而後從新執行:/usr/local/mysql/bin/mysql_secure_installation 就好了。

初始化完成以後,咱們使用備份的sql腳原本進行恢復:

[root@localhost ~]# mysql -uroot -p < gs_ngx_lua_backup.sql

執行完成以後,發現 gs 和 ngx_lua 數據庫都還原出來了,可是他們的數據不是最新的數據:

mysql> use gs;
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 user;
+----+----------+------+----------------+----------+
| id | name     | sex  | phone          | addr     |
+----+----------+------+----------------+----------+
|  1 | yuanfang |    1 | 14465463786    | hangzhou |
|  2 | Andy     |    0 | 14465463786    | beijing  |
|  3 | peter    |    0 | 14465463786    | Hongkong |
|  4 | lexin    |    1 | 36565634       | shenzhen |
|  5 | lexin2   |    1 | 43563436565634 | aomao    |
+----+----------+------+----------------+----------+
5 rows in set (0.01 sec)

這是由於,咱們尚未使用 mysql-bin.000027 和 mysql-bin.000028 兩個binary log。mysql-bin.000027 是咱們前面模擬的增量備份,而mysql-bin.000028 是 刪除data-dir目錄時,最新的binary log。依次應用了這兩個binary log以後,數據庫才能恢復到最新的狀態。

6)應用 binary log:

[root@localhost backup]# pwd
/backup
[root@localhost backup]# mysqlbinlog mysql-bin.000027 > 27.sql
[root@localhost backup]# mysqlbinlog mysql-bin.000028 > 28.sql

mysqlbinlog mysql-bin.000027 > 27.sql 獲得了 27.sql 和 28.sql 以後,使用 mysql 來執行:

mysql -uroot -p < 27.sql; 應用了增量備份的binary log.

而後查看數據:

mysql> mysql> select * from user;
+----+----------+------+-------------+----------+
| id | name     | sex  | phone       | addr     |
+----+----------+------+-------------+----------+
|  1 | yuanfang |    1 | 14465463786 | hangzhou |
|  2 | Andy     |    0 | 14465463786 | beijing  |
|  3 | peter    |    0 | 14465463786 | Hongkong |
|  4 | lexin    |    1 | 36565634    | shenzhen |
+----+----------+------+-------------+----------+
4 rows in set (0.00 sec)

然應用 28.sql :

mysql -uroot -p < 28.sql;

獲得最新的狀態:

mysql> select * from user;
+----+----------+------+-------------+----------+
| id | name     | sex  | phone       | addr     |
+----+----------+------+-------------+----------+
|  1 | yuanfang |    1 | 14465463786 | hangzhou |
|  2 | Andy     |    0 | 14465463786 | beijing  |
|  3 | peter    |    0 | 14465463786 | Hongkong |
+----+----------+------+-------------+----------+
3 rows in set (0.00 sec)

能夠看到,成功的還原到了刪除 data-dir 目錄以前的狀態了。

5. mysqldump的 坑

若是對 mysqldump 的默認啓用的選項不熟悉的話,可能會被默認啓用的選項 --add-drop-table 給坑了。由於默認會生成 drop table if exist 語句。可能會致使數據的丟失。  --add-drop-database 默認沒有啓用。若是不想他生成 drop table 語句,能夠加入 --skip-add-drop-table選項,或者 --add-ropt-table=0也能夠。

6. 總結:

1)邏輯備份的最佳方法:

全備:

mysqldump -uxxx -p --single-transaction --master-data=2 --routines --flush-logs --databases db1 db2 db3 > alldb.sql;

mysqldump -uxxx -p --flush-privileges --databases mysql > mysql.sql;

若是將mysql也一塊兒備份的話:

mysqldump -uxxx -p --single-transaction --master-data=2 --routines --flush-logs --flush-privileges --all-databases > alldb.sql;

有時,還須要加入:--default-character-set=utf8/utf8mb4 ,該選項通常也能夠配置在/etc/my.cnf中

增量備份:flush logs; 而後將binary log存儲起來便可。

2)搭建slave時的最佳選項:

mysqldump -uxxx -p --single-transaction --master-data=2 --routines --databases db1 db2 db3 > alldb.sql;

搭建slave,沒有必要 --flush-logs。固然搭建slave的最佳方式是使用 xtrabackup,物理備份。

3)使用mysqldump備份的sql腳本還原的方法:

先還原數據庫,而後應用增量日誌和最新日誌,binary log在應用以前須要使用mysqlbinlog命令來處理。

相關文章
相關標籤/搜索