初始環境
有一臺機器A安裝了MySQL5.7.20作爲主數據庫服務器,它已經運行了一段時間,具有小規模的數據。一個Web應用使用Spring+JPA+Hibernate來訪問這個數據庫。
目標
在機器B上安裝MySQL作爲slave數據庫服務器,與主數據庫形成主從複製架構。修改Web應用使讀寫分離,所有讀操作走slave數據庫,所有寫操作走master數據庫。
步驟
1.安裝備庫
在機器B上安裝MySQL5.7.20。參考官方文檔https://dev.mysql.com/doc/refman/5.7/en/linux-installation-rpm.html
2.創建複製賬號
在主庫上創建一個用戶,並賦予合適的權限。備庫將用這個用戶連接到主庫並讀取其二進制日誌。
mysql> grant replication slave,replication client on *.* to repl identified by 'Welcome1';
3. 配置主庫和備庫
在主庫上打開二進制日誌,並指定一個唯一的服務器ID。在主庫的my.cnf文件中增加或修改如下內容:
server-id = 43(服務器id,每臺機器要唯一,最好用IP最後一位)
log_bin = mysql-bin(這是主服務器,必須開啓log_bin,這句就是開啓了)
binlog_format = mixed(混合比較好,還有statements,rows)
binlog_do_db = master(需要同步的數據庫,如果多個數據庫,重複這個配置)
binlog_ignore_db = mysql(排除不需要同步的數據庫,如果多個數據庫,重複這個配置)
expire_logs_days = 7(二進制日誌自動刪除或過期的天數。默認爲0,不刪除)
slave_skip_errors = 1062 (跳過指定的錯誤,1062指主鍵重複,1032是主從數據庫不一致, 請百度更多)
binlog_cache_size = 1M (爲每個session分配的內存)
查看二進制日誌文件是否已經在主庫上建立。
mysql> show master status;
Empty set (0.00 sec)
說明二進制日誌文件還沒有建立。需要重啓MySQL服務,
sh-4.1# /sbin/service mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
再次查看,發現二進制日誌文件已經建立。
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)
備庫也需要在my.cnf中增加類似的配置,然後也需要重啓MySQL服務。
log_bin=mysql-bin
server_id=45
relay_log=/var/lib/mysql/mysql-relay-bin
log_slave_updates=1 (表示slave將複製事件寫進自己的二進制日誌)
read_only=1 (表示從節點只能讀,不能寫)
4. 啓動複製
我們要告訴備庫如何連接到主庫並重放其二進制日誌。
mysql> change master to master_host='host1',
-> master_user='repl',
-> master_password='Welcome1',
-> master_log_file='mysql-bin.000001',
-> master_log_pos=0;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
master_log_pos設置爲0,說明要從日誌開頭讀起。然後可以使用show slave status來檢查複製是否正確執行。
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: slc05ida.us.oracle.com
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
......
Seconds_Behind_Master: NULL
......
1 row in set (0.00 sec)
發現Slave_IO_State,Slave_IO_Running和Slave_SQL_Running三列顯示當前備庫複製還沒開始運行。而且日誌開頭是4,不是0。
運行下面的命令開始執行復制:
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: slc05ida.us.oracle.com
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 154
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
......
1 row in set (0.01 sec)
在主庫上執行show processlist\G可以看到複製線程。
mysql> show processlist\G
*************************** 5. row ***************************
Id: 9
User: repl
Host: slc10giz.us.oracle.com:40508
db: NULL
Command: Binlog Dump
Time: 93
State: Master has sent all binlog to slave; waiting for more updates
Info: NULL
5 rows in set (0.00 sec)
在備庫上執行show processlist\G可以看到一個I/O線程和一個SQL線程。
mysql> show processlist\G
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: starting
Info: show processlist
*************************** 2. row ***************************
Id: 5
User: system user
Host:
db: NULL
Command: Connect
Time: 152
State: Waiting for master to send event
Info: NULL
*************************** 3. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 151
State: Slave has read all relay log; waiting for more updates
Info: NULL
3 rows in set (0.00 sec)
5. 從主庫克隆數據
配置了上面的主從複製之後,我們發現備庫沒有獲得主庫原有的數據。因爲以上的主從複製只是同步配置主從複製之後發生的事件。我們需要用其他方法克隆主庫原來的數據。這裏我們使用mysqldump。它只是用於數據庫中只有InnoDB表的時候。
-bash-4.1$ /usr/bin/mysqldump --single-transaction --all-databases --master-data=1 --host=host1 -ufmwhatool -pfmwhatool| mysql --host=host2 -uroot -pWelcome1
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 3021 (HY000) at line 22: This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first.
mysqldump: Got errno 32 on write
看來我們需要先把主從複製關掉。
mysql> stop slave;
Query OK, 0 rows affected (0.03 sec)
-bash-4.1$ /usr/bin/mysqldump --single-transaction --all-databases --master-data=1 --host=1 -ufmwhatool -pfmwhatool| mysql --host=host2 -uroot -pWelcome1
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
這次沒有報錯。
過了一會兒,我們查看備庫,發現數據已經克隆過去了。
再用start slave;命令打開主從複製。
在主庫中某個Table裏插入記錄,就會發現從庫裏的這個Table裏馬上就有這條記錄了。
OK,到此主從複製成功。