雙機熱備:保持兩個數據庫的狀態自動同步。對任何一個數據庫的操作都自動同步到另外一個數據庫,始終保持兩個數據庫數據一致。
說到mysql的備份,那就必須要瞭解(不是理解)mysql的備份原理,借用一整很多大神都用的圖:
這個備份的過程分爲兩部分:
主(Master): 打開復制模式之後,主服務器Master, 會把自己的每一次改動都記錄到 二進制日誌 Binarylog 中。
從(Slave): 打開復制模式之後,從服務器Slave的I/O線程, 會用master上的賬號登陸到 master上, 讀取master的Binarylog, 寫入到自己的中繼日誌 Relaylog, 然後自己的sql線程會負責讀取這個中繼日誌,並執行一遍。 如是,主服務器上的更改就同步到從服務器上了。
實驗需求:
本次實驗用的是mysql5.7.20版本:
[root@ansible ~]# mysql -V
mysql Ver 14.14 Distrib 5.7.20, for Linux (x86_64) using EditLine wrapper
mysql5.7.20的安裝如果還有問題,可以借鑑:
http://blog.csdn.net/weixin_37998647/article/details/78649092
實驗兩臺主機的IP分別是:
192.168.1.121 我們稱之爲A,
192.168.1.185 我們稱之爲B,
方便起見,直接關掉防火牆,selinux
廢話已經太多了,下面直接開幹吧:
1、在A上給用於備份的用戶授權(我們直接用root用戶):
mysql> grant replication slave on *.* to 'root'@'192.168.1.185' identified by 'abc123';
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)
mysql> set global validate_password_length=6;
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to 'root'@'192.168.1.185' identified by 'abc123';
Query OK, 0 rows affected, 1 warning (0.01 sec)
(報錯是因爲密碼太簡單,該本版的mysql帶有密碼強壯度校驗的模塊,按照上面的方法設置一下就可以了。)
2. 開啓主服務器的 binarylog。
[root@ansible ~]# vim /etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin = mysql-bin
binlog_format = mixed
server-id = 1
read-only = 0
binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
binlog-ignore-db = zabbix
auto-increment-increment = 10
auto-increment-offset = 1
在最後面加了一些參數:
log-bin = mysql-bin
binlog_format = mixed
server-id = 1
read-only = 0
binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
binlog-ignore-db = zabbix
auto-increment-increment = 10
auto-increment-offset = 1
解釋一下這些參數的的意義:
server-id 必須保證每個服務器不一樣。 這可能和循環同步有關。 防止進入死循環。
binlog-do-db 用來表示,只把哪些數據庫的改動記錄到binary日誌中。 可以寫上關注hello數據庫。 也可以把它註釋掉了。 只是展示一下。 可以寫多行,表示關注多個數據庫。
binlog-ignore-db 表示,需要忽略哪些數據庫。我這裏忽略了其他的5個數據庫。
後面兩個用於在 雙主(多主循環)互相備份。 因爲每臺數據庫服務器都可能在同一個表中插入數據,如果表有一個自動增長的主鍵,那麼就會在多服務器上出現主鍵衝突。 解決這個問題的辦法就是讓每個數據庫的自增主鍵不連續。 我假設需要將來可能需要10臺服務器做備份, 所以auto-increment-increment 設爲10. 而 auto-increment-offset=1 表示這臺服務器的序號。 從1開始, 不超過auto-increment-increment。
這樣做之後, 我在這臺服務器上插入的第一個id就是 1, 第二行的id就是 11了, 而不是2,(同理,在第二臺服務器上插入的第一個id就是2, 第二行就是12, 這個後面再介紹) 這樣就不會出現主鍵衝突了。
保存, 重啓mysql。
- 獲取主服務器狀態, 和同步初態。
[root@ansible ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 775
Server version: 5.7.20-log MySQL Community Server (GPL)
Copyright (c) 2000, 2017, 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> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hello |
| mysql |
| performance_schema |
| sys |
| zabbix |
+--------------------+
8 rows in set (0.00 sec)
如果是剛安裝的就沒有“hello”和zabbix“”這兩個庫,上面我們已經設置了備份不管zabbix庫,這裏只關注hello庫就好了。
先鎖定 hello數據庫:
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.15 sec)
導出數據,我們這裏只用導出hello數據庫,(如果你有多個數據庫作爲初態的話, 需要導出所有這些數據庫:)
[root@ansible ~]# mysqldump --master-data -uroot -p hello > hello.sql
Enter password:
[root@ansible ~]# ll
-rw-r--r-- 1 root root 2632 Jan 22 13:36 hello.sql
然後查看A服務器的binary日誌位置:
記住這個文件名和 位置, 等會在從服務器上會用到。
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 1277
Binlog_Do_DB:
Binlog_Ignore_DB: information_schema,mysql,performance_schema,sys,zabbix
Executed_Gtid_Set:
1 row in set (0.00 sec)
ERROR:
No query specified
Master上的操作已經OK了, 可以解除鎖定了:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
把導出的hello.sql傳到185上去。
[root@ansible ~]# scp hello.sql 192.168.1.185:
hello.sql 100% 2632 2.6KB/s 00:00
- 設置從服務器 B 需要複製的數據庫
打開從服務器 B 的 /etc/my.cnf 文件:
[root@localhost ~]# vim /etc/my.cnf
在配置文件最後加上:
log-bin = mysql-bin
binlog_format = mixed
server-id = 2
replicate-ignore-db = information_schema
replicate-ignore-db = mysql
replicate-ignore-db = performance_schema
replicate-ignore-db = sys
replicate-ignore-db = zabbix
relay_log = mysqld-relay-bin
log-slave-updates = ON
解釋一下參數:
server-id 必須保證每個服務器不一樣。 這可能和循環同步有關。 防止進入死循環。
replicate-ignore-db 複製時需要排除的數據庫, 我使用了,這個。 除開系統的幾個數據庫和zabbix之外,所有的數據庫都複製。
relay_log 中繼日誌的名字。 前面說到了, 複製線程需要先把遠程的變化拷貝到這個中繼日誌中, 在執行。
log-slave-updates 意思是,中繼日誌執行之後,這些變化是否需要計入自己的binarylog。 當你的B服務器需要作爲另外一個服務器的主服務器的時候需要打開。 就是雙主互相備份,或者多主循環備份。 我們這裏需要, 所以打開。
保存, 重啓mysql。
- 從上導入初態。
把剛纔從A服務器上導出的 hello.sql 導入到 B的hello數據庫中, 如果B現在沒有hello數據庫,請先創建一個, 然後再導入:
創建數據庫:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hello |
| mysql |
| performance_schema |
| sys |
| zabbix |
+--------------------+
6 rows in set (0.00 sec)
mysql> drop database hello;
Query OK, 0 rows affected (0.01 sec)
mysql> create database hello default charset utf8;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hello |
| mysql |
| performance_schema |
| sys |
| zabbix |
+--------------------+
6 rows in set (0.00 sec)
把hello.sql 上傳到B上, 然後導入:
[root@localhost ~]# mysql -uroot -p hello < hello.sql
Enter password:
開啓同步, 在B服務器上執行:
mysql> change master to master_host='192.168.1.121',master_user='root',master_password='abc123',master_log_file='mysql-bin.000001',master_log_pos=1277;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
重啓mysql,查看slave狀態:
[root@localhost ~]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
[root@localhost ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.7.20-log MySQL Community Server (GPL)
Copyright (c) 2000, 2017, 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> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.121
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 1277
Relay_Log_File: mysqld-relay-bin.000003
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: information_schema,mysql,performance_schema,sys,zabbix
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
……
至此,主從複製已經配置好了。現在測試一下:
在A上:
mysql> create database test;
Query OK, 1 row affected (0.03 sec)
B上show databases;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hello |
| mysql |
| performance_schema |
| sys |
| test |
| zabbix |
+--------------------+
說明主從複製已經成功了
如果只要求主從複製,那麼到這裏已經完成了,後面的內容可以不需再看
此時暫且不要在B上操作。
上面的結果已經看到A上的操作可以自動同步到B上,但是B上的操作還不能同步到A上。
如果要做B複製到A,跟上面的操作基本一樣,那下面的操作就不解釋了。
主主複製,即互爲主備,雙機熱備:
1. 在B中創建用戶;
mysql> grant replication slave on *.* to 'root'@'192.168.1.121' identified by 'abc123';
Query OK, 0 rows affected, 1 warning (0.01 sec)
- 打開 /etc/my.cnf , 開啓B的binarylog:
[root@localhost ~]# vim /etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin = mysql-bin
binlog_format = mixed
server-id = 2
replicate-ignore-db = information_schema
replicate-ignore-db = mysql
replicate-ignore-db = performance_schema
replicate-ignore-db = sys
replicate-ignore-db = zabbix
relay_log = mysqld-relay-bin
log-slave-updates = ON
read-only = 0
binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
binlog-ignore-db = zabbix
auto-increment-increment = 10
auto-increment-offset = 2
- 此時不需要導出B的初態了,因爲它剛剛纔從A導過來。 直接記住它的master日誌狀態:
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000003
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB: information_schema,mysql,performance_schema,sys,zabbix
Executed_Gtid_Set:
1 row in set (0.00 sec)
ERROR:
No query specified
- 登錄到A 服務器。 開啓中繼:
[root@ansible ~]# vim /etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin = mysql-bin
binlog_format = mixed
server-id = 1
read-only = 0
binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
binlog-ignore-db = zabbix
auto-increment-increment = 10
auto-increment-offset = 1
replicate-ignore-db = information_schema
replicate-ignore-db = mysql
replicate-ignore-db = performance_schema
replicate-ignore-db = sys
replicate-ignore-db = zabbix
relay_log = mysqld-relay-bin
log-slave-updates = ON
- 啓動同步:
mysql> change master to master_host = '192.168.1.185',master_user='root',master_password='abc123',master_log_file='mysql-bin.000003',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.09 sec)
然後重啓mysql服務。
然後查看,slave狀態是否正常:
如果出現:
Slave_IO_Running: No
Slave_SQL_Running: No
解決辦法:先停掉mysql服務。 找到這三個文件,把他們刪掉。 一定要先停掉mysql服務。不然還是不成功。你需要重啓一下機器了。 或者手動kill mysqld。
[root@ansible ~]# cd /var/lib/mysql
[root@ansible mysql]# rm -fr relay-log.info ansible-relay-bin.000001 ansible-relay-bin.index
再登錄啓動同步,之後再重啓
mysql> change master to master_host = '192.168.1.185',master_user='root',master_password='abc123',master_log_file='mysql-bin.000003',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.09 sec)
重啓之後再查看:
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.185
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: mysqld-relay-bin.000003
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: information_schema,mysql,performance_schema,sys,zabbix
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
……
出現連個NO的原因是:是因爲我們在配置A的中繼文件時改了中繼文件名,但是mysql沒有同步。
至此主主同步已經開啓了。
驗證一下,方法在B上插入數據,在A上查看。
===============================================
下面介紹一下基於gtid模式的複製配置:
配置文件的最後加上gtid_mode=on ; enforce_gtid_consistency=on 這兩項。即
主的配置:
# cat /etc/my.cnf
log-bin=mysql-bin
binlog_format=mixed
server-id=1
auto-increment-increment = 2
auto-increment-offset = 1
gtid_mode=on
enforce_gtid_consistency=on
從的配置:
gtid_mode=on
enforce_gtid_consistency=on
log-bin = mysql-bin
binlog_format = mixed
server-id = 2
主給從授權:
grant replication slave on *.* to 'root'@192.168.1.121 identified by 'abc123';
從找主:
change master to master_host='192.168.1.185',master_user='ha',master_password='Lockey+123',master_auto_position=1;
線上業務量比較大的時候,往往主庫會不停的寫入,此時就需要用到gtid 模式。他的好處就是,出庫不用鎖庫,而且自動找到position 的位置,不用擔心position不停變化而無法同步。