概念
主從復制可以使MySQL數據庫主服務器的主數據庫,復制到一個或多個MySQL從服務器從數據庫,默認情況下,復制異步; 根據配置,可以復制數據庫中的所有數據庫,選定的數據庫或甚至選定的表。
MySQL中主從復制的優點
橫向擴展解決方案
在多個從庫之間擴展負載以提高性能。在這種環境中,所有寫入和更新在主庫上進行。但是,讀取可能發生在一個或多個從庫上。該模型可以提高寫入的性能(由於主庫專用於更新),同時在多個從庫上讀取,可以大大提高讀取速度。
數據安全性
由於主庫數據被復制到從庫,從庫可以暫停復制過程,可以在從庫上運行備份服務,而不會破壞對應的主庫數據。
分析
可以在主庫上創建實時數據,而信息分析可以在從庫上進行,而不會影響主服務器的性能。
長距離數據分發
可以使用復制創建遠程站點使用的數據的本地副本,而無需永久訪問主庫。
1. 准備工作
關閉防火牆:systemctl stop firewalld.service
MySQL主:server-01
MySQL從:server-02
首先在兩台機器上裝上,保證正常啟動,可以使用;
2.Master-Server 配置
修改 my.cnf
配置 Master 以使用基於二進制日志文件位置的復制,必須啟用二進制日志記錄並建立唯一的服務器ID,否則則無法進行主從復制。
停止MySQL服務。
service mysql.server stop
開啟binlog ,每台設置不同的 server-id
$ cat /etc/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1
啟動MySQL服務
service mysql.server start
登錄MySQL
systemctl start mysql.server
創建用戶
每個從庫使用MySQL用戶名和密碼連接到主庫,因此主庫上必須有用戶帳戶,從庫可以連接。任何帳戶都可以用於此操作,只要它已被授予 REPLICATION SLAVE
權限。可以選擇為每個從庫創建不同的帳戶,或者每個從庫使用相同帳戶連接到主庫
雖然不必專門為復制創建帳戶,但應注意,復制用到的用戶名和密碼會以純文本格式存儲在主信息存儲庫文件或表中 。因此,需要創建一個單獨的帳戶,該帳戶只具有復制過程的權限,以盡可能減少對其他帳戶的危害。
主庫上創建主從復制賬號
登錄MySQL
systemctl start mysql.server
創建用戶【MySQL8.0.11和之前不一樣】
必須先創建用戶
密碼規則:mysql8.0以上密碼策略限制必須要大小寫加數字特殊符號):
再進行賦值:
CREATE USER 'replication'@'主MySQLip或域名' IDENTIFIED BY '輸入的密碼;
GRANT REPLICATION SLAVE ON *.* TO 'replication'@'主MySQLip或域名';
flush privileges;
3. Slave-Server 配置
修改 my.cnf
停止MySQL服務。
service mysql.server stop
$ cat /etc/my.cnf
[mysqld]
server-id=2
如果要設置多個從庫,則每個從庫的server-id與主庫和其他從庫設置不同的唯一值。
啟動MySQL服務
service mysql.server start
配置主庫通信
查看 Master-Server , binlog File 文件名稱和 Position值位置 並且記下來
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 629 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
要設置從庫與主庫進行通信,進行復制,使用必要的連接信息配置從庫在從庫上執行以下語句
將選項值替換為與系統相關的實際值
參數格式,請勿執行
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name',
-> MASTER_PORT=3306,
-> MASTER_USER='replication_user_name',
-> MASTER_PASSWORD='replication_password',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.252.123',
-> MASTER_PORT=3306,
-> MASTER_USER='replication',
-> MASTER_PASSWORD='mima',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=629;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
MASTER_LOG_POS=0
寫成0 也是可以的
放在一行執行方便
CHANGE MASTER TO MASTER_HOST='主MySQL服務器ip', MASTER_PORT=3306, MASTER_USER='replication', MASTER_PASSWORD='replication賬號密碼', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=629;
啟動從服務器復制線程
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
查看復制狀態
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.252.123
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 629
Relay_Log_File: master2-relay-bin.000003
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
檢查主從復制通信狀態
Slave_IO_State
#從站的當前狀態
Slave_IO_Running
: Yes #讀取主程序二進制日志的I/O線程是否正在運行
Slave_SQL_Running
: Yes #執行讀取主服務器中二進制日志事件的SQL線程是否正在運行。與I/O線程一樣
Seconds_Behind_Master
#是否為0,0就是已經同步了
必須都是 Yes
如果不是原因主要有以下 4 個方面:
1、網絡不通
2、密碼不對
3、MASTER_LOG_POS 不對 ps
4、mysql 的 auto.cnf server-uuid 一樣(可能你是復制的mysql)
$ find / -name 'auto.cnf'
$ cat /var/lib/mysql/auto.cnf
[auto]
server-uuid=6b831bf3-8ae7-11e7-a178-000c29cb5cbc # 按照這個16進制格式,修改server-uuid,重啟mysql即可
4. 測試主從復制
啟動MySQL服務-主從都啟動
systemctl mysql.server start
登錄MySQL-主從都登錄
mysql -uroot -p
在 Master-Server 創建測試庫
mysql> CREATE DATABASE `replication_test`;
mysql> use `replication_test`;
mysql> CREATE TABLE `sync_test` (`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
在 Slave-Server 查看是否同步過來
mysql> show databases;
+-------------------------+
| Database |
+-------------------------+
| information_schema |
| mysql |
| performance_schema |
| replication_wwww.ymq.io |
| sys |
+-------------------------+
mysql> use replication_test
mysql> show tables;
+-----------------------------------+
| Tables_in_replication_test |
+-----------------------------------+
| sync_test |
+-----------------------------------+
1 row in set (0.00 sec)
一些命令
查看主服務器的運行狀態
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1190 | | | |
+------------------+----------+--------------+------------------+-------------------+
查看從服務器主機列表
mysql> show slave hosts;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 2 | | 3306 | 1 | 6b831bf2-8ae7-11e7-a178-000c29cb5cbc |
+-----------+------+------+-----------+--------------------------------------+
獲取binlog文件列表
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 1190 |
+------------------+-----------+
只查看第一個binlog文件的內容
mysql> mysql> show binlog events;
+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.19-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000001 | 420 | Anonymous_Gtid | 1 | 485 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 485 | Query | 1 | 629 | GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.252.124' |
| mysql-bin.000001 | 629 | Anonymous_Gtid | 1 | 694 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 694 | Query | 1 | 847 | CREATE DATABASE `replication_wwww.ymq.io` |
| mysql-bin.000001 | 847 | Anonymous_Gtid | 1 | 912 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 912 | Query | 1 | 1190 | use `replication_wwww.ymq.io`; CREATE TABLE `sync_test` (`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
查看指定binlog文件的內容
mysql> mysql> show binlog events in 'mysql-bin.000001';
+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.19-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000001 | 420 | Anonymous_Gtid | 1 | 485 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 485 | Query | 1 | 629 | GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.252.124' |
| mysql-bin.000001 | 629 | Anonymous_Gtid | 1 | 694 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 694 | Query | 1 | 847 | CREATE DATABASE `replication_wwww.ymq.io` |
| mysql-bin.000001 | 847 | Anonymous_Gtid | 1 | 912 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 912 | Query | 1 | 1190 | use `replication_wwww.ymq.io`; CREATE TABLE `sync_test` (`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
+------------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
啟動從庫復制線程
mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.00 sec)
停止從庫復制線程
mysql> STOP SLAVE;
Query OK, 0 rows affected (0.00 sec)
5. 復制實現細節分析
MySQL主從復制功能使用三個線程實現,一個在主服務器上,兩個在從服務器上
1. Binlog轉儲線程
當從服務器與主服務器連接時,主服務器會創建一個線程將二進制日志內容發送到從服務器。
該線程可以使用 語句 SHOW PROCESSLIST
(下面有示例介紹) 在服務器 sql 控制台輸出中標識為Binlog Dump線程。
二進制日志轉儲線程獲取服務器上二進制日志上的鎖,用於讀取要發送到從服務器的每個事件。一旦事件被讀取,即使在將事件發送到從服務器之前,鎖會被釋放。
2. 從服務器I/O線程
當在從服務器sql 控制台發出 START SLAVE
語句時,從服務器將創建一個I/O線程,該線程連接到主服務器,並要求它發送記錄在主服務器上的二進制更新日志。
從機I/O線程讀取主服務器Binlog Dump線程發送的更新 (參考上面 Binlog轉儲線程 介紹),並將它們復制到自己的本地文件二進制日志中。
該線程的狀態顯示詳情 Slave_IO_running 在輸出端 使用 命令SHOW SLAVE STATUS
使用\G語句終結符,而不是分號,是為了,易讀的垂直布局
這個命令在上面 查看從服務器狀態 用到過
SHOW SLAVE STATUS\G
3. 從服務器SQL線程
從服務器創建一條SQL線程來讀取由主服務器I/O線程寫入的二級制日志,並執行其中包含的事件。
在前面的描述中,每個主/從連接有三個線程。主服務器為每個當前連接的從服務器創建一個二進制日志轉儲線程,每個從服務器都有自己的I/O和SQL線程。
從服務器使用兩個線程將讀取更新與主服務器更新事件,並將其執行為獨立任務。因此,如果語句執行緩慢,則讀取語句的任務不會減慢。
例如,如果從服務器開始幾分鍾沒有運行,或者即使SQL線程遠遠落后,它的I/O線程也可以從主服務器建立連接時,快速獲取所有二進制日志內容。
如果從服務器在SQL線程執行所有獲取的語句之前停止,則I/O線程至少獲取已經讀取到的內容,以便將語句的安全副本存儲在自己的二級制日志文件中,准備下次執行主從服務器建立連接,繼續同步。
使用命令 SHOW PROCESSLIST\G
可以查看有關復制的信息
命令 SHOW FULL PROCESSLISTG
在 Master 主服務器 執行的數據示例
mysql> SHOW FULL PROCESSLIST\G
*************************** 1. row ***************************
Id: 22
User: repl
Host: node2:39114
db: NULL
Command: Binlog Dump
Time: 4435
State: Master has sent all binlog to slave; waiting for more updates
Info: NULL
Id: 22是Binlog Dump服務連接的從站的復制線程
Host: node2:39114 是從服務,主機名 級及端口
State: 信息表示所有更新都已同步發送到從服務器,並且主服務器正在等待更多更新發生。
如果Binlog Dump在主服務器上看不到 線程,意味着主從復制沒有配置成功; 也就是說,沒有從服務器連接主服務器。
命令 SHOW PROCESSLISTG
在 Slave 從服務器 ,查看兩個線程的更新狀態
mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 6810
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 7
User: system user
Host:
db: NULL
Command: Connect
Time: 3069
State: Slave has read all relay log; waiting for more updates
Info: NULL
Id: 6是與主服務器通信的I/O線程
Id: 7是正在處理存儲在中繼日志中的更新的SQL線程
在 運行 SHOW PROCESSLIST
命令時,兩個線程都空閑,等待進一步更新
如果在主服務器上在設置的超時,時間內 Binlog Dump線程沒有活動,則主服務器會和從服務器斷開連接。超時取決於的 服務器系統變量 值 net_write_timeout(在中止寫入之前等待塊寫入連接的秒數,默認10秒)和 net_retry_count;(如果通信端口上的讀取或寫入中斷,請在重試次數,默認10次) 設置
該SHOW SLAVE STATUS語句提供了有關從服務器上復制處理的附加信息。請參見 第16.1.7.1節“檢查復制狀態”。