1,概述
MySQL數(shù)據(jù)庫自身提供的主從復(fù)制功能,可以方便地實(shí)現(xiàn)數(shù)據(jù)的多處自動備份,完成Mysql的分布式部署。多個(gè)數(shù)據(jù)備份,解決了以下幾個(gè)問題:
- 數(shù)據(jù)的安全性,不易丟失。
- 讀寫分離,提高數(shù)據(jù)庫的讀寫性能。
- 數(shù)據(jù)庫的負(fù)載均衡,提高數(shù)據(jù)庫的高可用和容錯(cuò)性。
2,Mysql主從復(fù)制的基本原理和步驟
2.1,基本介紹
MySQL內(nèi)建的復(fù)制功能是構(gòu)建大型、高性能應(yīng)用程序的基礎(chǔ)。將MySQL的數(shù)億分布到到多個(gè)系統(tǒng)上去,這種分步的機(jī)制,是通過將MySQL的某一臺主機(jī)(Master)的數(shù)據(jù)復(fù)制到其它主機(jī)(Slave)上,并重新執(zhí)行一遍來實(shí)現(xiàn)的。復(fù)制過程中,一臺服務(wù)器充當(dāng)Master,而一個(gè)或多個(gè)其它服務(wù)器充當(dāng)Slave。
2.2,實(shí)現(xiàn)步驟
MySQL之間數(shù)據(jù)復(fù)制的基礎(chǔ)是二進(jìn)制日志文件(binary log file)。一臺MySQL數(shù)據(jù)庫一旦啟用二進(jìn)制日志后,其作為master,它的數(shù)據(jù)庫中所有操作都會以“事件”的方式記錄在二進(jìn)制日志中,其他數(shù)據(jù)庫作為slave通過一個(gè)【I/O線程】與主服務(wù)器保持通信,并監(jiān)控master的二進(jìn)制日志文件的變化,如果發(fā)現(xiàn)master二進(jìn)制日志文件發(fā)生變化,則會把變化復(fù)制到自己的中繼日志中,然后slave的一個(gè) 【SQL線程】會把相關(guān)的“事件”執(zhí)行到自己的數(shù)據(jù)庫中,以此實(shí)現(xiàn)從數(shù)據(jù)庫和主數(shù)據(jù)庫的一致性,也就實(shí)現(xiàn)了主從復(fù)制。
主從復(fù)制過程,可以簡化為三個(gè)步驟:
- Master將改變記錄到二進(jìn)制日志中。
- Slave將Master的二進(jìn)制日志拷貝到它的中繼日志(Relay_log)。
- Slave重做中繼日志中的事件,將改變反映它自己的數(shù)據(jù)。
- 注意:在主從復(fù)制架構(gòu)中,所有對參與主從復(fù)制的數(shù)據(jù)表的更新操作,必須在主服務(wù)器上進(jìn)行。
2.3,典型的應(yīng)用場景
在一主多從的數(shù)據(jù)庫體系中,多個(gè)從服務(wù)器采用異步的方式更新主數(shù)據(jù)庫的變化,業(yè)務(wù)服務(wù)器在執(zhí)行寫或者相關(guān)修改數(shù)據(jù)庫的操作是在主服務(wù)器上進(jìn)行的,讀操作則是在各從服務(wù)器上進(jìn)行。
2.4. MySQL支持的復(fù)制類型
基于語句的復(fù)制
在主服務(wù)器上執(zhí)行的SQL語句,在從服務(wù)器上執(zhí)行同樣的語句。否則,你必須要小心,以避免用戶對主服務(wù)器上的表進(jìn)行的更新與對服務(wù)器上的表所進(jìn)行的更新之間的沖突。
配置:binlog_format = 'STATEMENT'基于行的復(fù)制
把改變的內(nèi)容復(fù)制過去,而不是把命令在從服務(wù)器上執(zhí)行一遍,從 MySQL 5.0開始支持。
配置:binlog_format = 'ROW'混合類型的復(fù)制
默認(rèn)采用基于語句的復(fù)制,一旦發(fā)現(xiàn)基于語句的無法精確的復(fù)制時(shí),就會采用基于行的復(fù)制。
配置:binlog_format = 'MIXED'
3,實(shí)現(xiàn)過程(采用Docker方式部署)
3.1,準(zhǔn)備工作
- 查找mysql的docker鏡像
kevin@apple:~$ docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relati... 5693 [OK]
mariadb MariaDB is a community-developed fork of M... 1767 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Crea... 391 [OK]
percona Percona Server is a fork of the MySQL rela... 317 [OK]
zabbix/zabbix-server-mysql Zabbix Server with MySQL database support 80 [OK]
hypriot/rpi-mysql RPi-compatible Docker Image with Mysql 79
centurylink/mysql Image containing mysql. Optimized to be li... 58 [OK]
zabbix/zabbix-web-nginx-mysql Zabbix frontend based on Nginx web-server ... 42 [OK]
tutum/mysql Base docker image to run a MySQL database ... 31
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 25 [OK]
mysql/mysql-cluster Experimental MySQL Cluster Docker images. ... 19
centos/mysql-57-centos7 MySQL 5.7 SQL database server 18
schickling/mysql-backup-s3 Backup MySQL to S3 (supports periodic back... 16 [OK]
linuxserver/mysql A Mysql container, brought to you by Linux... 14
zabbix/zabbix-proxy-mysql Zabbix proxy with MySQL database support 10 [OK]
centos/mysql-56-centos7 MySQL 5.6 SQL database server 8
openshift/mysql-55-centos7 DEPRECATED: A Centos7 based MySQL v5.5 ima... 6
circleci/mysql MySQL is a widely used, open-source relati... 3
frodenas/mysql A Docker Image for MySQL 3 [OK]
dsteinkopf/backup-all-mysql backup all DBs in a mysql server 3 [OK]
inferlink/landmark-mysql landmark-mysql 0 [OK]
ansibleplaybookbundle/mysql-apb An APB which deploys RHSCL MySQL 0 [OK]
cloudposse/mysql Improved `mysql` service with support for ... 0 [OK]
cloudfoundry/cf-mysql-ci Image used in CI of cf-mysql-release 0
openzipkin/zipkin-mysql Mirror of https://quay.io/repository/openz... 0
- 創(chuàng)建網(wǎng)絡(luò),docker有四種網(wǎng)絡(luò)類型(bridge、container、host和none),我們使用的是none,可以設(shè)置靜態(tài)IP
kevin@apple:~$ docker network create --subnet=172.18.0.0/24 my_network
0b85ab8c7809886bb7fada8c4a8970b5692f11dbd950790f1e9b1e098691f114
- 啟動新容器master,命名為mysql_master,設(shè)置靜態(tài)IP為172.18.0.10
kevin@apple:~$ docker run -it --name mysql_master -h mysql_master \
-p 13306:3306 --net my_network --ip 172.18.0.10 \
--add-host mysql_master:172.18.0.10 \
mysql:latest /bin/bash
- 啟動新容器slave,命名為mysql_slave,設(shè)置靜態(tài)IP為172.18.0.11
kevin@apple:~$ docker run -it --name mysql_slave -h mysql_slave \
-p 13307:3306 --net my_network --ip 172.18.0.11 \
--add-host mysql_master:172.18.0.10 \
mysql:latest /bin/bash
- 在docker容器中,部署相關(guān)軟件
root@mysql_master:~$ apt-get update
root@mysql_master:~$ apt-get install vim
# 安裝ifconfig、netstat
root@mysql_master:~$ apt-get install net-tools
3.2,主服務(wù)器
- 開啟二進(jìn)制日志,并配置唯一的server-id
# 在[mysqld]下增加配置
root@mysql_master:/etc/mysql/mysql.conf.d# vi /etc/mysql/mysql.conf.d/mysqld.cnf
...
...
# 開啟二進(jìn)制日志,可以寫絕對路徑,例如/var/log/mysql/master-bin
log-bin = mysql-bin
# Mysql服務(wù)ID,必須保證唯一
server-id = 1
# 不進(jìn)行主從復(fù)制的db
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
# 進(jìn)行主從復(fù)制的db
binlog-do-db = test
# 只保存最近7天的bin-log文件,避免文件過多
expire_logs_days=7
- 重啟Mysql服務(wù)
root@mysql_master:/etc/mysql/mysql.conf.d# service mysql restart
- 創(chuàng)建一個(gè)用于slave和master通信的用戶賬號slave1
mysql> CREATE USER 'slave1'@'%' IDENTIFIED BY '123456';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'%';
- 創(chuàng)建測試賬號和數(shù)據(jù)庫
mysql> Grant all privileges on *.* to 'test'@'%' identified by '123456' with grant option;
mysql> Create database test;
- 查看master狀態(tài),獲得master二進(jìn)制日志文件名及位置
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000005 | 955 | test | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)
3.3,從服務(wù)器
- 配置唯一的server-id
# 在[mysqld]下增加配置
root@mysql_slave:/etc/mysql/mysql.conf.d# vi /etc/mysql/mysql.conf.d/mysqld.cnf
...
...
# Mysql服務(wù)ID,必須保證唯一
server-id = 2
- 使用master分配的用戶賬號讀取master二進(jìn)制日志
mysql> CHANGE MASTER TO
MASTER_HOST='mysql_master',
MASTER_USER='slave1',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000005',
MASTER_LOG_POS=955;
- 啟用slave服務(wù),并查看狀態(tài)
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql_master
Master_User: slave1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 1424
Relay_Log_File: mysql_slave-relay-bin.000004
Relay_Log_Pos: 1637
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes # IO線程是啟動狀態(tài),如果是No,可以查看下面日志,分析處理
Slave_SQL_Running: Yes # SQL線程是啟動狀態(tài),如果是No,可以查看下面日志,分析處理
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1424
Relay_Log_Space: 2016
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 0f5421ba-0ede-11e8-b442-0242ac12000a
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
4,測試
4.1,測試用例1
- 在master中,創(chuàng)建數(shù)據(jù)表,增加2行數(shù)據(jù),觀察slave數(shù)據(jù)變化是否一致(結(jié)果一致)
mysql> CREATE TABLE test.`student` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
mysql> Insert into test.student(name) values('aaa');
mysql> Insert into test.student(name) values('bbb');
mysql> Select * from test.student;
4.2,測試用例2
- 在master中,刪除1行數(shù)據(jù),更新1行數(shù)據(jù),觀察slave的數(shù)據(jù)變化(結(jié)果一致)
mysql> delete from test.student where id = 1;
mysql> update test.student set name = 'ccc' where id = 2;
4.3,測試用例3
- 在master中,刪除1個(gè)數(shù)據(jù)表,觀察slave的數(shù)據(jù)變化(結(jié)果一致)
mysql> drop table student;
4.4,測試用例4
- 在master中,刪除數(shù)據(jù)庫test,或創(chuàng)建數(shù)據(jù)庫test,觀察slave的數(shù)據(jù)變化(結(jié)果一致)
mysql> drop database test;
mysql> create database test;
5,高級應(yīng)用
5.1,數(shù)據(jù)庫復(fù)制
如果是新部署的MySQL主從服務(wù)器,這一步不需要。
如果Master之前有數(shù)據(jù),需要把Master的數(shù)據(jù)導(dǎo)出并還原到Slave上,要保證Master和Slave服務(wù)器中的數(shù)據(jù)是一樣的。
建議導(dǎo)出Master庫的時(shí)候進(jìn)行鎖表,導(dǎo)完后再解鎖。
- 鎖表,并查看master的bin-log日志文件名稱和位置
mysql> flush tables with read lock;
mysql> show master status;
- 全量導(dǎo)出Master數(shù)據(jù)庫
root@mysql_master:/home# mysqldump -utest -p123456 test > test.sql
- 手動導(dǎo)入到Slave
root@mysql_slave:/home# mysql -utest -p123456 -e 'create database test;'
root@mysql_slave:/home# mysql -utest -p123456 -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
root@mysql_slave:/home# mysql -utest -p123456 test < test.sql
- 解鎖master數(shù)據(jù)庫
mysql> unlock tables;
5.2,MySQL主從一致性檢查
- 寫一個(gè)監(jiān)控腳本,用來監(jiān)控Slave中的兩個(gè)"yes",如果只有一個(gè)"yes"或者零個(gè),就表明主從有問題。
- 通過Percona-Toolkit這個(gè)工具來實(shí)現(xiàn)的,Percona Toolkit是一組高級的命令行工具,用來管理MySQL和系統(tǒng)任務(wù)。
6,參考
官方文檔
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-replication.htmlMySQL主從復(fù)制(Master-Slave)實(shí)踐
https://www.cnblogs.com/gl-developer/p/6170423.htmlMySQL 主從復(fù)制詳解(詳細(xì))
http://blog.csdn.net/u010098331/article/details/50828820Mysql常用命令行大全
http://www.cnblogs.com/bluecobra/archive/2012/01/11/2318922.html