MySQL復制
(1)擴展方式: Scale Up ,Scale Out
(2)MySQL的擴展
讀寫分離
復制:每個節點都有相同的數據集
向外擴展
二進制日志
單向
(3)復制的功用:
數據分布 負載均衡讀 備份 高可用和故障切換 MySQL升級測試
一主多從

主從復制原理

(1)從庫生成兩個線程,一個I/O線程,一個SQL線程; (2)i/o線程去請求主庫 的binlog,並將得到的binlog日志寫到relay log(中繼日志) 文件中;主庫會生成一個 log dump 線程,用來給從庫 i/o線程傳binlog; (3)SQL 線程,會讀取relay log文件中的日志,並解析成具體操作,來實現主從的操作一致,而最終數據一致;
主從復制線程:
主節點:
dump Thread:為每個Slave的I/O Thread啟動一個dump線程,用於向其發送binary log events
從節點:
I/O Thread:向Master請求二進制日志事件,並保存於中繼日志中 SQL Thread:從中繼日志中讀取日志事件,在本地完成重放
跟復制功能相關的文件:
master.info:用於保存slave連接至master時的相關信息,例如賬號、密碼、服務器地址等 relay-log.info:保存在當前slave節點上已經復制的當前二進制日志和本地replay log日志的對應關系
主從復制特點:
異步復制 主從數據不一致比較常見
復制架構:
Master/Slave, Master/Master, 環狀復制 一主多從 從服務器還可以再有從服務器 一從多主:適用於多個不同數據庫 主主
復制需要考慮二進制日志事件記錄格式
STATEMENT(5.0之前) ROW(5.1之后,推薦) MIXED
主從配置過程:參看官網
https://mariadb.com/kb/en/library/setting-up-replication/
https://dev.mysql.com/doc/refman/5.5/en/replication-configuration.html
實現主從復制架構:
(1)先在B主機(從服務器)相關的配置文件,配置數據庫文件時,最好確保主從的數據庫為空
[root@centos7-1data]#vim /etc/my.cnf [mysqld] read-only # 只讀權限,對於普通用戶無法修改,但是root用戶可以進行修改 server-id=2 log_bin=/data/logbin/mysql-bin # 指定二進制日志路徑 binlog_format=row # 二進制日志保存格式 relay_log=relay-log # 開啟中繼日志 log_slave_updates = 1 # 默認是關閉狀態,打開后才能復制主服務器的二進制日志,此項很重要
(2)配置A主機(主服務器)的配置文件
[mysqld] server-id=1 log_bin=/data/logbin/mysql-bin binlog_format=ROW 將二進制日志按行顯示,保證二進制日志不丟失 skip-name-resolve # 不將IP地址解析為名稱
(3)重啟機器A(主服務器)的mysql服務並在mysql數據庫中創建從復制權限的用戶賬號
[root@centos7data]#systemctl restart mariadb [root@centos7data]#mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 2 Server version: 5.5.60-MariaDB MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> show master logs; # 復制之前查看要復制文件的起始位置與文件大小。 +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 26756 | | mysql-bin.000002 | 921736 | | mysql-bin.000003 | 245 | +------------------+-----------+ MariaDB [(none)]> grant replication slave on *.* to repluser@'192.168.34.%' identified by 'centos'; 創建復制權限的用戶賬號 Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]>
在主服務導入一個數據庫模板,准備讓從服務器進行復制
[root@centos7~]#mysql < hellodb_innodb.sql
(4)重啟從服務器的mysql數據庫,在從服務器上設置,使用有復制權限的用戶賬號連接至主服務器,並啟動復制線程
可以在help幫助中查看模板,方便寫入重要信息:
MariaDB [(none)]> help change master to 幫助可以看到相關模板 CHANGE MASTER TO MASTER_HOST='master2.mycompany.com', 主服務器地址 MASTER_USER='replication', 主服務器創建有復制權限的服務名 MASTER_PASSWORD='bigs3cret', 密碼 MASTER_PORT=3306, MASTER_LOG_FILE='master2-bin.001', 二進制日志 MASTER_LOG_POS=4, 從二進制日志多大開始復制

MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.101',
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000003',
-> MASTER_LOG_POS=245;
查看導入的模板信息:
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.34.101 主服務器IP地址
Master_User: repluser 主服務器名
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003 從000003開始復制
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000001 復制過來的數據庫名
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: No
Slave_SQL_Running: No
(5)在從服務器開始復制
MariaDB [(none)]> start slave; Query OK, 0 rows affected (0.03 sec)
此時可以跟蹤一下從服務器復制狀態,出現的是I/O線程過程
MariaDB [(none)]> show processlist; +----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+----------+ | Id | User | Host | db | Command | Time | State | Info | Progress | +----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+----------+ | 5 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 | | 6 | system user | | NULL | Connect | 69 | Waiting for master to send event | NULL | 0.000 | | 7 | system user | | NULL | Connect | 1817 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL | 0.000 | +----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+----------+ 3 rows in set (0.00 sec)
(6)此時在從服務器查看復制后的數據庫內容,已經將主服務器的數據庫內容全部復制過來
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
(7)查看主服務器當前的線程情況,出現的就是dump線程過程
MariaDB [(none)]> show processlist
-> ;
+----+----------+----------------------+------+-------------+------+-----------------------------------------------------------------------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+----------+----------------------+------+-------------+------+-----------------------------------------------------------------------+------------------+----------+
| 2 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 |
| 8 | repluser | 192.168.34.102:56744 | NULL | Binlog Dump | 218 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL | 0.000 |
+----+----------+----------------------+------+-------------+------+-----------------------------------------------------------------------+------------------+----------+
若要繼續添加新salve,實現一主多從
(1)在第二個從服務器上修改配置文件
[root@centos7-1data]#vim /etc/my.cnf [mysqld] read-only # 只讀權限,對於普通用戶無法修改,但是root用戶可以進行修改 server-id=3 # server ID要不一致 log_bin=/data/logbin/mysql-bin # 指定二進制日志路徑 binlog_format=row # 二進制日志保存格式 relay_log=relay-log # 開啟中繼日志 log_slave_updates = 1 # 使主服務器的數據寫進二進制日志中
(2)重啟第二個從服務器mysql數據庫
[root@10-9-122-130~]#systemctl restart mariadb
(3)在生產中,如果之前的數據庫數據已經很大,需要新加一個slave數據庫,可以將之前的數據庫進行完全備份,對新的數據進行主從復制:在主服務器上備份當前的數據庫信息
MariaDB [(none)]> show master logs; # 備份前,可以看到主服務器的起始二進制日志文件大小是245,mysql-bin.000004 +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 26756 | | mysql-bin.000002 | 921736 | | mysql-bin.000003 | 7583 | | mysql-bin.000004 | 245 | +------------------+-----------+ 4 rows in set (0.00 sec) [root@centos7~]#mysqldump -A -F --single-transaction --master-data=1 > /data/all_bak.sql 主服務器上備份數據庫信息,--master-data=1的1適用於主從復制中 [root@centos7~]#scp /data/all_bak.sql 192.168.34.103:/data/ 然后將備份的數據庫傳到第二個從服務器的data目錄下 all_bak.sql
修改復制到第二個從服務器的備份數據,將主機名、賬號、密碼及端口寫入即可,而實際的二進制文件的大小和文件名已經存在,在第二個從服務器導入時,就不需要再寫change master to

(4)在第二個從服務器修改備份數據內容,作為從服務器啟動復制線程
CHANGE MASTER TO MASTER_HOST='192.168.34.101', MASTER_USER='repluser', MASTER_PASSWORD='centos', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=245;
(5)在第二個從服務器上修改完備份內容后,直接導入到mysql數據庫中,並進行復制主服務器數據庫
[root@centos7-2 data]# mysql < all_bak.sql 將備份數據庫存放在mysql數據庫中 MariaDB [(none)]> start slave; 啟動從服務器復制 MariaDB [(none)]> show databases;查看此時的數據庫已經復制過來 +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
驗證一主多從服務器關系
在主服務器上創建新的數據庫:
MariaDB [(none)]> create database db1; Query OK, 1 row affected (0.00 sec) MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec)
在從服務器1上查看是否復制了數據庫db1
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec)
在從服務器2上查看是否復制了數據庫db1
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec)
解除主從關系,恢復獨立的服務器,並將從服務器作為主節點服務器
現在,當主服務器down機后,可以將從服務器1作為主服務器,從服務器2作為從服務器
如果主節點已經運行了一段時間,且有大量數據時,如何配置並啟動slave節點
通過備份恢復數據至從服務器 復制起始位置為備份時,二進制日志文件及其POS
(1)將從服務器1的復制線程停止
MariaDB [(none)]> stop slave;
(2)將從服務器1節點全部刪除,准備做為主服務器
MariaDB [(none)]> reset slave all; MariaDB [(none)]> show slave status; 此時查看沒有從服務器節點
(3)在從服務器1修改為以下配置文件內容:vim /etc/my.cnf
[mysqld] server-id=2 log_bin=/data/logbin/mysql-bin binlog_format=row relay_log=relay-log skip-name-resolve
(4)在從服務器1上查看當前的二進制日志信息,做為第二個從服務器復制的起始文件大小和名稱
MariaDB [(none)]> show master logs; +--------------------+-----------+ | Log_name | File_size | +--------------------+-----------+ | mariadb-bin.000001 | 245 | +--------------------+-----------+ 1 row in set (0.00 sec)
(5)在從服務器2清除master.info ,relay-log.info, relay log ,開始新的relay log ,注意:需要先STOP SLAVE
stop slave; reset slave all;
(6)在從服務器2上開啟復制線程
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.102', # 當前主服務器的IP地址
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000001',
-> MASTER_LOG_POS=245;
(7)啟動從服務器2的復制功能
start slave
驗證主從復制結果
MariaDB [(none)]> create database haha1; #在主服務器上新建數據庫 Query OK, 1 row affected (0.00 sec) MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | haha | | haha1 | | hellodb | | lisi | | mysql | | performance_schema | | test | +--------------------+ 9 rows in set (0.01 sec)
查看從服務器復制的結果
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec)
實驗:主從級聯復制
實現原理:在主從復制的基礎上,主從之間存在一個級聯復制的從服務器,當級聯復制的主機復制了主服務器的數據,級聯復制主機充當為主服務器,從服務器復制級聯復制主機的數據及二進制日志數據。
注意:中間級聯復制的主機無法將二進制日志傳遞到其他從服務器上,因此需要加上log_slave_updates選項,目的是為了將主服務器的二進制日志文件能寫入到從服務器上。
如果要啟用級聯復制,需要在從服務器啟用以下配置,log_slave_updates很關鍵,為了實時更新主服務器的二進制日志信息。
環境准備:
A機器作為主服務器:192.168.34.101
B機器作為中間級聯復制從服務器:192.168.34.102
C機器作為從服務器 :192.168.34.103
在A主服務器上配置相關文件:
(1)配置mysql數據庫配置文件中進行相關配置
vim /etc/my.cnf [mysqld] server-id=1 log_bin=/data/logbin/mysql-bin binlog_format=ROW
(2)啟動數據庫服務
systemctl start mariadb
將之前緩存的二進制日志全部清除
show master logs; 查看二進制日志 reset master; 清空二進制日志
(3)查看主服務器的二進制日志信息
MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 245 | +------------------+-----------+ 1 row in set (0.00 sec)
(4)登陸mysql賬號,並創建一個只有復制權限的賬號
MariaDB [(none)]> grant replication slave on *.* to rpl@'192.168.34.%' identified by 'centos';
在從服務器B上修改相關配置文件
(1)修改mysql配置文件
vim /etc/my.cnf [mysqld] server-id=2 binlog_format=ROW log_bin=/data/logbin/mysql-bin read-only log_slave_updates # 將主服務器的二進制日志更新到本機的級聯主機上,下一個從服務器進行復制二進制日志
(2)啟動mysql服務器
[root@centos7-1~]#systemctl start mariadb
最好先看看中間級聯復制的而二進制日志的起始位置,雖然默認是從服務器從245起點開始復制級聯機器的數據,有時系統起始復制位置不是245,從節點有可能無法從245開始復制級聯復制機器的數據。
[root@centos7 ~]# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 11 Server version: 10.3.10-MariaDB-log MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 351 | | mysql-bin.000002 | 328 | +------------------+-----------+ 2 rows in set (0.001 sec) MariaDB [(none)]> reset master ; Query OK, 0 rows affected (0.009 sec) MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 245 | +------------------+-----------+ 1 row in set (0.000 sec)
(3)啟動復制線程
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.101',
-> MASTER_USER='rpl',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=245; 注意:指定數據庫從頭開始復制
Query OK, 0 rows affected (0.01 sec)
(4)啟動slave,並查看當前的啟動狀態
MariaDB [(none)]> start slave; 開啟slave功能
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 395
Relay_Log_File: centos7-1-relay-bin.000002
Relay_Log_Pos: 690
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes #yes就是表示開啟
Slave_SQL_Running: Yes
對比主從復制結果
(1)在主服務器上導入數據庫內容
[root@centos7~]#mysql < hellodb_innodb.sql 導入數據庫 MariaDB [(none)]> show databases; 查看數據庫內容 +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.01 sec)
(2)在從服務器查看已經復制了主服務器的數據庫內容
[root@centos7-1mysql]#mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 24 Server version: 10.2.29-MariaDB-log MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> show databases; 此時看到已經復制了主服務器的數據庫內容 +--------------------+ | Database | +--------------------+ | hellodb | | information_schema | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.01 sec)
在從服務器C上配置相關文件
(1)配置第二個從服務器配置文件
vim /etc/my.cnf [mysqld] server-id=3 read-only
重啟mysql服務
systemctl restart mariadb
(2)查看B從服務器的二進制日志信息,此時的日志大小已經是7308,如果從7308開啟復制進程,前面復制的數據庫全部都不會復制,因此,我們前面已經查出級聯機器是從245有二進制日志,默認的數據是從245開始復制,如果級聯復制不是從245開始,就需要從查到的開始進行復制。
MariaDB [(none)]> show master logs; +--------------------+-----------+ | Log_name | File_size | +--------------------+-----------+ | mariadb-bin.000001 | 7308 | +--------------------+-----------+
(3)在C主機配置復制線程文件,並開啟復制線程
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.102', #指向B主機的IP地址
-> MASTER_USER='rpl',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000001',
-> MASTER_LOG_POS=245;
(4)在C主機開啟slave開關
start slave
(5)在C主機查看slave開啟狀態
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.102
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 7308
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 7594
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
此時在C從服務器中查看已經復制了B從服務器的數據庫信息
MariaDB [hellodb]> show databases; +--------------------+ | Database | +--------------------+ | hellodb | | information_schema | | mysql | | performance_schema | | test | +--------------------+
復制架構中應該注意的問題:
1、限制從服務器為只讀 在從服務器上設置read_only=ON 最好使用read_only選項 注意:此限制對擁有SUPER權限的用戶均無效 阻止所有用戶, 包括主服務器復制的更新 mysql> FLUSH TABLES WITH READ LOCK; 最好不要加此選項,會阻止從服務器復制的更新 2、RESET SLAVE 在從服務器清除master.info ,relay-log.info, relay log ,開始新的relay log ,注意:需要先STOP SLAVE RESET SLAVE ALL 清除所有從服務器上設置的主服務器同步信息如:PORT, HOST, USER和 PASSWORD 等 3、sql_slave_skip_counter = N # 從服務器忽略幾個主服務器的復制事件,global變量,生產中比較實用,可以忽略錯誤繼續往下復制,否則因為一個錯誤不能往下復制,會導致后續的數據不能復制。
如何保證主從復制的事務安全
參看https://mariadb.com/kb/en/library/server-system-variables/
在master節點啟用參數:
sync_binlog=1 # 每次寫后立即同步二進制日志到磁盤,性能差 如果用到的為InnoDB存儲引擎: innodb_flush_log_at_trx_commit=1 # 每次事務提交立即同步日志寫磁盤 innodb_support_xa=ON # 默認值,分布式事務MariaDB10.3.0廢除 sync_master_info=# #次事件后master.info同步到磁盤
在slave節點啟用服務器選項:
skip_slave_start=ON # 不自動啟動slave,skip是忽略slave啟動,不要關閉。
在slave節點啟用參數:
sync_relay_log=# #次寫后同步relay log到磁盤 sync_relay_log_info=# #次事務后同步relay-log.info到磁盤
實驗:sql_slave_skip_counter跳過復制錯誤用法
在主服務器上查看一個表的詳細情況
MariaDB [hellodb]> select * from teachers; 可以看到此時的teachers表序列號是4
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)
MariaDB [hellodb]> desc teachers; 我們可以看到序列號是自動增長,TID為主鍵
+--------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+---------+----------------+
| TID | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(100) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | YES | | NULL | |
+--------+----------------------+------+-----+---------+----------------+
在從服務器上查看一個表的詳細情況
MariaDB [hellodb]> select * from teachers; 可以看到此時的teachers表序列號是4
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)
MariaDB [hellodb]> desc teachers; 我們可以看到序列號是自動增長,TID為主鍵
+--------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+---------+----------------+
| TID | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| Name | varchar(100) | NO | | NULL | |
| Age | tinyint(3) unsigned | NO | | NULL | |
| Gender | enum('F','M') | YES | | NULL | |
+--------+----------------------+------+-----+---------+----------------+
下來我們先在B從服務器的teachers表添加數據,添加的haha的TID是6,就會與主服務器的TID存在沖突,就無法復制主無服務器的信息
MariaDB [hellodb]> insert teachers(name)value('biubiu');
Query OK, 1 row affected, 1 warning (0.01 sec)
MariaDB [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | lisi | 0 | NULL |
| 6 | haha | 0 | NULL |
| 7 | biubiu | 0 | NULL |
+-----+---------------+-----+--------+
我們在主服務器的teachers表添加數據,此時添加的wang的TID是6
MariaDB [hellodb]> insert teachers(name)value('wang');
Query OK, 1 row affected, 1 warning (0.02 sec)
MariaDB [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | lisi | 0 | NULL |
| 6 | wang | 0 | NULL |
+-----+---------------+-----+--------+
下來我們在B從服務器上查看slave狀態,可以明確的看到錯誤信息,是因為主鍵6存在錯誤
MariaDB [hellodb]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 7924
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 8014
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table hellodb.teachers; Duplicate entry '6' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000001, end_log_pos 7897
Skip_Counter: 0
Exec_Master_Log_Pos: 7730
Relay_Log_Space: 8504
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1062 錯誤編號
Last_SQL_Error: Could not execute Write_rows event on table hellodb.teachers; Duplicate entry '6' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000001, end_log_pos 7897
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
停止slave,然后再設置跳過此次的錯誤信息
MariaDB [hellodb]> stop slave;
我們在B服務器上進行修改跳過一個錯誤的操作
MariaDB [hellodb]> set global sql_slave_skip_counter=1; 由於只有一個錯誤,就修改為1
查看跳過的信息
MariaDB [hellodb]> select @@sql_slave_skip_counter; +--------------------------+ | @@sql_slave_skip_counter | +--------------------------+ | 1 | +--------------------------+
開啟slave
MariaDB [hellodb]> start slave;
啟動slave,查看slave狀態,並查看復制的結果,此時會跳過主服務器沖突的TID,從服務器繼續復制之后的信息
MariaDB [hellodb]> show slave status\G; 查看當前slave狀態
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 8508
Relay_Log_File: mariadb-relay-bin.000004
Relay_Log_Pos: 529
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
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: 8508
Relay_Log_Space: 1693
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
MariaDB [hellodb]> select * from teachers; 此時跳過了沖突的TID,不會復制主服務器沖突TID的信息,直接復制下面的信息
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | lisi | 0 | NULL |
| 6 | haha | 0 | NULL |
| 7 | biubiu | 0 | NULL |
| 8 | zhangsan | 0 | NULL |
| 9 | wo | 0 | NULL |
+-----+---------------+-----+--------+
沖突的TID=6,可以手動在B從服務器上修改,保證與主服務器一致
MariaDB [hellodb]> update teachers set name='wang' where tid=6; 修改tid=6的相關信息 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [hellodb]> select * from teachers; +-----+---------------+-----+--------+ | TID | Name | Age | Gender | +-----+---------------+-----+--------+ | 1 | Song Jiang | 45 | M | | 2 | Zhang Sanfeng | 94 | M | | 3 | Miejue Shitai | 77 | F | | 4 | Lin Chaoying | 93 | F | | 5 | lisi | 0 | NULL | | 6 | wang | 0 | NULL | | 7 | biubiu | 0 | NULL | | 8 | zhangsan | 0 | NULL | | 9 | wo | 0 | NULL | +-----+---------------+-----+--------+
主主復制
主主復制:互為主從
(1)容易產生的問題:數據不一致;因此慎用
(2)考慮要點:自動增長id
配置一個節點使用奇數id
auto_increment_offset=1 開始點 auto_increment_increment=2 增長幅度
另一個節點使用偶數id
auto_increment_offset=2 auto_increment_increment=2
主主復制的配置步驟:
(1) 各節點使用一個惟一server_id (2) 都啟動binary log和relay log (3) 創建擁有復制權限的用戶賬號 (4) 定義自動增長id字段的數值范圍各為奇偶 (5) 均把對方指定為主節點,並啟動復制線程
實驗:主主復制
先在A主服務器上修改mysql配置文件
vim /etc/my.cnf [mysqld] server-id=1 log_bin=/data/logbin/mysql-bin binlog_format=ROW auto_increment_offset=1 auto_increment_increment=2
重啟A機器mysql服務器
systemctl reatart mariadb
在B主服務器上修改mysql配置文件
vim /etc/my.cnf [mysqld] server-id=2 log_bin binlog_format=ROW auto_increment_offset=2 auto_increment_increment=2
重啟B主機的mysql服務
systemctl restart mariadb
在A主機上創建復制權限的賬號
MariaDB [(none)]> grant replication slave on *.* to rpl@'192.168.34.%' identified by 'centos';
查看A主機當前的二進制日志文件大小
MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 245 | +------------------+-----------+
然后在B主機上啟動復制線程
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.101',
-> MASTER_USER='rpl',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000001', 指定A主機的二進制日志初始文件
-> MASTER_LOG_POS=245; 初始的二進制日志文件大小
在B主機上啟動slave
MariaDB [(none)]> start slave; 啟動slave
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 401
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 685
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes 查看此時已經啟動IO_slave
Slave_SQL_Running: Yes 已經啟動SQL_slave
在A主機上導入數據庫,並查看數據庫內容
[root@centos7~]#mysql < hellodb_innodb.sql [root@centos7~]#mysql MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+
在B主機上查看復制A主機的數據庫是否成功,此時已經復制成功,實現主主單向復制,下來我們還需要實現主主雙向復制
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test |
在B主機上查看二進制日志情況
MariaDB [(none)]> show master logs; +--------------------+-----------+ | Log_name | File_size | +--------------------+-----------+ | mariadb-bin.000001 | 245 | +--------------------+-----------+
然后在A主機上開啟復制線程,指定B主機的詳細信息
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.102',
-> MASTER_USER='rpl',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000001',
-> MASTER_LOG_POS=245;
啟動A主機的slave,並查看狀態
MariaDB [(none)]> start slave; 開啟slave
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.102
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 531
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes 此時已經開啟IO
Slave_SQL_Running: Yes 此時開啟SQL
此時,我們來看一下A主機創建一個表,並插入表信息,此時的ID號以奇數開始增漲
MariaDB [hellodb]> create table t1(id int auto_increment primary key,name char(10)); 創建表t1
Query OK, 0 rows affected (0.03 sec)
MariaDB [hellodb]> insert t1(name)value('a'); 插入a信息
Query OK, 1 row affected (0.01 sec)
MariaDB [hellodb]> insert t1(name)value('b'); 插入b信息
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from t1;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 3 | b |
+----+------+
在B主機上插入表格信息,此時在B主機上插入信息,會以偶數遞增序列號,不會和A主機存在沖突
MariaDB [hellodb]> insert t1(name)value('a'); 在B主機上插入a信息
Query OK, 1 row affected (0.01 sec)
MariaDB [hellodb]> insert t1(name)value('b'); 在B主機上插入b信息
Query OK, 1 row affected (0.00 sec)
MariaDB [hellodb]> select * from t1; 查看此時未出現沖突情況,但是ID順序會比較亂
+----+------+
| id | name |
+----+------+
| 1 | a |
| 3 | b |
| 4 | a |
| 6 | b |
+----+------+
主從復制的半同步復制
原理:介於異步復制和全同步復制之間,主庫在執行完客戶端提交的事務后不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於異步復制,半同步復制提高了數據的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步復制最好在低延時的網絡中使用。
默認情況下,MySQL的復制功能是異步的,異步復制可以提供最佳的性能,主庫把binlog日志發送給從庫即結束,並不驗證從庫是否接收完畢。這意味着當主服務器或從服務器端發生故障時,有可能從服務器沒有接收到主服務器發送過來的binlog日志,這就會造成主服務器和從服務器的數據不一致,甚至在恢復時造成數據的丟失

實驗:先配置主從復制,再配置半同步復制(生產中常用此配置)
A機器為主服務器
B為第一個從服務器
C為第二個從服務器
啟動三個服務器的mysql服務
# systemctl start mariadb
配置主服務器的相關配置
(1)配置主服務器的mysql配置
[root@centos7~]#vim /etc/my.cnf [mysqld] server-id=1 log_bin=/data/logbin/mysql-bin binlog_format=ROW
(2)清空之前實驗的二進制日志文件,(注意,在生產環境中不要這么做),並查看當前的二進制日志情況
MariaDB [(none)]> reset master; MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 245 | +------------------+-----------+
(3)主服務器上創建授權復制賬號
[root@centos7~]#mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 2 Server version: 5.5.60-MariaDB MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> grant replication slave on *.* to rpl@'192.168.34.%' identified by 'centos';
在從服務器配置相關文件
(1)在B從服務器mysql數據庫配置文件
server-id=2 #配置server-id,讓從服務器有唯一ID號 relay_log = relay-log #打開Mysql中繼日志,日志格式為二進制 read_only = 1 #設置只讀權限 log_bin = /data/mysql/mysql-bin #開啟從服務器二進制日志(非必須) log_slave_updates = 1 #使得更新的數據寫進二進制日志中
(2)在B從服務器mysql數據庫中啟動復制線程
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.101', 配置主服務器的IP地址
-> MASTER_USER='rpl',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000001',指定主服務器二進制日志的文件
-> MASTER_LOG_POS=245; 指定初始二進制日志的文件大小
開啟slave並查看slave狀態
start slave
查看slave狀態
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 396
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 680
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes 查看IO已開啟
Slave_SQL_Running: Yes 查看SQL已開啟
(4)在C從服務器上設置mysql配置文件
server-id=3 #配置server-id,讓從服務器有唯一ID號 relay_log = relay-log #打開Mysql中繼日志,日志格式為二進制 read_only = 1 #設置只讀權限 log_bin = /data/logbin/mysql-bin #開啟從服務器二進制日志,(非必須) log_slave_updates = 1 #使得更新的數據寫進二進制日志中
(5)在C從服務器mysql數據庫中啟動復制線程
CHANGE MASTER TO MASTER_HOST='192.168.34.101', 指定主服務器IP地址 MASTER_USER='rpl', MASTER_PASSWORD='centos', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=245; 主服務器的二進制日志初始值
(6)啟動slave並查看狀態
MariaDB [(none)]> start slave; 啟動slave
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.102
Master_User: rpl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 531
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes 此時的IO已開啟
Slave_SQL_Running: Yes 此時的SQL已開啟
驗證主從復制效果:
(1)在主服務器導入數據庫
[root@centos7~]#mysql < hellodb_innodb.sql MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
在B從服務器查看復制結果
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
在C從服務器查看復制結果
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
下來查詢半同步插件配置,並配置半同步相關實
/usr/lib64/mysql/plugin/semisync_master.so /usr/lib64/mysql/plugin/semisync_slave.so
(1)在主服務器上安裝插件
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
(2)查看安裝后的插件名
MariaDB [(none)]> show plugins; | Name | Status | Type | Library | License rpl_semi_sync_master(對用插件文件名) | ACTIVE | REPLICATION | semisync_master.so | GPL
(3)啟動插件
MariaDB [(none)]> show global variables like 'rpl_semi%'; 查看是否開啟 MariaDB [(none)]> set global rpl_semi_sync_master_enabled = on; 開啟插件,此時看見只是臨時啟動,要長久使用需要加入到配置文件中
將插件永久啟動:寫入配置文件中
[mysqld] server-id=1 log_bin=/data/logbin/mysql-bin binlog_format=ROW rpl_semi_sync_master_enabled
重新啟動mysql服務
systemctl restart mariadb
設置超時時長
mysql>SET GLOBAL rpl_semi_sync_master_timeout = 1000;超時長為1s
查看變量信息
mysql>SHOW GLOBAL VARIABLES LIKE '%semi%';

查看狀態變量
mysql>SHOW GLOBAL STATUS LIKE '%semi%';

在B從服務器上設置相關配置:
(1)安裝從節點插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
(2)啟動插件,將插件寫入配置文件中,永久保存
mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1;臨時啟動插件
永久保存在文件中,並重啟mysql服務 systemctl restart mariadb
vim /etc/m.cnf [mysqld] server-id=2 read-only log_bin rpl_semi_sync_slave_enabled
查看B從服務器的插件狀態是否啟用
SHOW GLOBAL STATUS LIKE '%semi%';
在C從服務器上做相同的配置
(1)安裝插件
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
(2)啟動插件,最好將插件保存在配置文件中
mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1;臨時啟動插件
修改在配置文件中,永久保存,並重啟mysql服務:systemctl restart mariadb
vim /etc/m.cnf [mysqld] server-id=3 read-only rpl_semi_sync_slave_enabled
查看C從服務器狀態是否已經啟用插件:
SHOW GLOBAL STATUS LIKE '%semi%';
查看插件啟用狀態:
MariaDB [(none)]> select @@rpl_semi_sync_slave_enabled;

在主節點上查看此時開啟的插件狀態

下來我們要實現半同步實驗,必須將兩個從服務器的slave功能重啟才可以生效
# stop slave; # start slave;
超時時間默認是10s,我們可以將此選項設置2s,提升用戶感知,修改完之后重啟mysql服務即可
vim /etc/my.cnf [mysqld] rpl_semi_sync_master_timeout=2000
實現主從從架構及復制過濾器

復制過濾原理:復制過濾器:(黑、白名單)僅復制有限一個或幾個數據庫相關的數據,而非所有;由復制過濾器進行;
有兩種實現思路:
(1) 服務器選項:主服務器僅向二進制日志中記錄與特定數據庫相關的事件 注意:此項和binlog_format相關 參看:https://mariadb.com/kb/en/library/mysqld-options/#-binlog-ignore-db binlog_do_db = 數據庫白名單列表,多個數據庫需多行實現 binlog_ignore_db = 數據庫黑名單列表 問題:基於二進制還原將無法實現;不建議使用 (2) 從服務器SQL_THREAD在replay中繼日志中的事件時,僅讀取與特定數據庫(特定表)相關的事件並應用於本地 問題:會造成網絡及磁盤IO浪費 建議使用此方法,在從服務器上配置 從服務器上的復制過濾器相關變量 replicate_do_db= # 指定復制庫的白名單,僅允許從復制這個庫的二進制日志 replicate_ignore_db= # 指定復制庫黑名單,除了這個數據庫,其他都允許復制 replicate_do_table= # 指定復制表的白名單 replicate_ignore_table= # 指定復制表的黑名單 replicate_wild_do_table= foo%.bar% 支持通配符 replicate_wild_ignore_table=
查看復制過濾器相關變量
MariaDB [hellodb]> show variables like 'replicate%'; +----------------------------------+-----------+ | Variable_name | Value | +----------------------------------+-----------+ | replicate_annotate_row_events | OFF | | replicate_do_db | | | replicate_do_table | | | replicate_events_marked_for_skip | replicate | | replicate_ignore_db | | | replicate_ignore_table | | | replicate_wild_do_table | | | replicate_wild_ignore_table | | +----------------------------------+-----------+
第一種方法:在從服務器上指定特定數據庫進行復制(推薦)
(1)在B從服務器修改/etc/my.cnfl配置文件並重啟mysql服務器
server-id=2 #配置server-id,讓從服務器有唯一ID號 relay_log = relay-log #打開Mysql日志,日志格式為二進制 read_only = 1 #設置只讀權限 log_bin = /data/logbin/mysql-bin #開啟從服務器二進制日志,(必須) log_slave_updates = 1 #使得更新的數據寫進二進制日志中 replicate_do_db=hellodb # 過濾hellodb數據庫,只復制此數據庫
(2)在C服務器修改mysql配置文件並重啟mysql服務器
server-id=3 #配置server-id,讓從服務器有唯一ID號 relay_log = relay-log #打開Mysql日志,日志格式為二進制 read_only = 1 #設置只讀權限 log_bin = /data/logbin/mysql-bin #開啟從服務器二進制日志,(必須) log_slave_updates = 1 #使得更新的數據寫進二進制日志中 replicate_do_db=hellodb # 過濾hellodb數據庫,只復制此數據庫
驗證過濾hellodb數據庫結果
在A主服務器上hellodb數據庫的teachers表中插入內容
MariaDB>use hellodb;
MariaDB [hellodb]> insert teachers(name)value('biu');在hellodb數據庫的teachers表中插入內容
在A從服務器mysql數據庫創建一個db1數據庫
MariaDB [hellodb]> create database db1; Query OK, 1 row affected (0.00 sec) MariaDB [hellodb]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | hellodb | | mysql | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec)
在B從服務msyql服務器中查看A主服務器創建的數據庫內容
MariaDB [hellodb]> select * from teachers; ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 4 Current database: hellodb +-----+---------------+-----+--------+ | TID | Name | Age | Gender | +-----+---------------+-----+--------+ | 1 | Song Jiang | 45 | M | | 2 | Zhang Sanfeng | 94 | M | | 3 | Miejue Shitai | 77 | F | | 4 | Lin Chaoying | 93 | F | | 5 | a | 0 | NULL | | 6 | biu | 0 | NULL | +-----+---------------+-----+--------+
此時查看新建的db1數據庫無法復制
MariaDB [hellodb]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+
在C從服務器查看A主服務器創建的數據庫
MariaDB [hellodb]> select * from teachers; ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 4 Current database: hellodb +-----+---------------+-----+--------+ | TID | Name | Age | Gender | +-----+---------------+-----+--------+ | 1 | Song Jiang | 45 | M | | 2 | Zhang Sanfeng | 94 | M | | 3 | Miejue Shitai | 77 | F | | 4 | Lin Chaoying | 93 | F | | 5 | a | 0 | NULL | | 6 | biu | 0 | NULL | +-----+---------------+-----+--------+
此時查看新建的db1數據庫無法復制
MariaDB [hellodb]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | hellodb | | mysql | | performance_schema | | test | +--------------------+
第二種方法:在主服務器上設置復制指定的數據庫和二進制日志(生產中不推薦)
vim /etc/my.cnf [mysqld] [mysqld] server-id=1 log_bin=/data/logbin/mysql-bin binlog_format=ROW binlog_do_db=hellodb # 只復制hellodb數據庫及二進制日志 binlog_do_db=db1 # 只復制db1數據庫及二進制日志
重啟msyql服務:systemctl restart mariadb
刪除B和C從服務器的配置文件:replicate_do_db=hellodb 並重啟mysql服務:systemctl restart mariadb,做此實驗室需要將以上的實驗配置文件先刪除。
由於上面做的實驗,創建了db1,當時從服務器未復制db1數據庫,此時我們可以在主服務器上刪除db1重新創建db1
(1)在A主服務器上刪除db1數據庫
drop database db1;
(2)在B和C從服務器都操作slave,跳過當前錯誤復制過程
MariaDB [hellodb]> stop slave; 先停止slave MariaDB [hellodb]> set global sql_slave_skip_counter=1; 跳過當前復制錯誤 MariaDB [hellodb]> start slave; 開啟slave
(3)此時在A主服務器上創建db1數據庫
MariaDB [hellodb]> create database db1;
(4)查看此時B和C從服務器的數據庫復制情況
MariaDB [hellodb]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | db1 | | hellodb | | mysql | | performance_schema | | test | +--------------------+
(5)在A主服務器上查詢白名單狀態
MariaDB [hellodb]> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000003 | 599 | hellodb,db1 | | +------------------+----------+--------------+------------------+
MySQL復制加密
基於SSL復制:
在默認的主從復制過程或遠程連接到MySQL/MariaDB所有的鏈接通信中的數據都是明文的,外網里訪問數據或則復制,存在安全隱患。通過SSL/TLS加密的方式進行復制的方法,來進一步提高數據的安全性
配置實現:
參看:https://mariadb.com/kb/en/library/replication-with-secure-connections/
主服務器開啟SSL:[mysqld] 加一行ssl 主服務器配置證書和私鑰;並且創建一個要求必須使用SSL連接的復制賬號 從服務器使用CHANGER MASTER TO 命令時指明ssl相關選項
實驗:開始對mysql復制加密
(1)在A主服務器創建一個存放文件的目錄ssl
[root@centos7~]#cd /etc/my.cnf.d [root@centos7my.cnf.d]#ls client.cnf mysql-clients.cnf server.cnf [root@centos7my.cnf.d]#mkdir ssl 創建一個ssl目錄 [root@centos7my.cnf.d]#cd ssl
(2)在A主服務器生成私鑰文件
[root@centos7ssl]#(umask 066;openssl genrsa 2048 >cakey.pem) Generating RSA private key, 2048 bit long modulus ..............................................................+++ .................+++ e is 65537 (0x10001) [root@centos7ssl]#ll total 4 -rw------- 1 root root 1679 Nov 26 16:55 cakey.pem
(3)在A主服務器創建自簽名證書
[root@centos7ssl]#openssl req -new -x509 -key cakey.pem -out cacert.pem -days 3650 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:beijing Locality Name (eg, city) [Default City]:beijing Organization Name (eg, company) [Default Company Ltd]:magedu Organizational Unit Name (eg, section) []:devops Common Name (eg, your name or your server's hostname) []:ca.magedu.com Email Address []:
(4)A主服務器申請證書
[root@centos7ssl]#openssl req -newkey rsa:2048 -days 365 -nodes -keyout master.key > master.csr 此時的-nodes是私鑰不加密的意思 Generating a 2048 bit RSA private key ...........+++ ................................................................................+++ writing new private key to 'master.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:beijing Locality Name (eg, city) [Default City]:beijing Organization Name (eg, company) [Default Company Ltd]:magedu Organizational Unit Name (eg, section) []:devops Common Name (eg, your name or your server's hostname) []:master.magedu.com Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
(5)在A主服務器上替從服務器申請證書
[root@centos7ssl]#openssl req -newkey rsa:2048 -days 365 -nodes -keyout slave.key > slave.csr Generating a 2048 bit RSA private key ...........................................................................................................+++ .............................................+++ writing new private key to 'slave.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:beijing Locality Name (eg, city) [Default City]:beijing Organization Name (eg, company) [Default Company Ltd]:magedu Organizational Unit Name (eg, section) []:devops Common Name (eg, your name or your server's hostname) []:slave.magedu.com Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
(6)在A主服務器頒發CA證書
[root@centos7ssl]#openssl x509 -req -in master.csr -CA cacert.pem -CAkey cakey.pem -set_serial 01 > master.crt 給master.csr文件頒發CA證書,編號為01,保存為master.csr文件 Signature ok subject=/C=CN/ST=beijing/L=beijing/O=magedu/OU=devops/CN=master.magedu.com Getting CA Private Key
(7)查看頒發CA證書信息
[root@centos7ssl]#openssl x509 -in master.crt -noout -text;
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=beijing, L=beijing, O=magedu, OU=devops, CN=ca.magedu.com
Validity
Not Before: Nov 26 09:08:12 2019 GMT
Not After : Dec 26 09:08:12 2019 GMT
Subject: C=CN, ST=beijing, L=beijing, O=magedu, OU=devops, CN=master.magedu.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ca:62:10:3d:a6:63:e2:ed:eb:3c:19:30:66:4e:
2a:cf:2e:8f:1c:86:31:70:f5:c8:8c:4d:e3:78:5a:
96:2b:4f:68:fb:e7:27:d6:43:a5:8b:67:5a:25:af:
2a:a9:5e:d4:65:8d:30:83:e0:7b:b5:9d:7b:9b:a9:
2d:b9:4b:ca:88:23:13:20:a4:6f:82:5b:ce:42:89:
82:6f:02:9f:0a:64:55:99:2f:60:7c:ad:ce:56:16:
4a:73:06:86:c7:04:b1:39:e2:f4:cb:45:f1:8f:1d:
1a:7d:b3:a8:1b:58:e0:a7:69:78:9e:f5:81:a8:2a:
f5:f1:73:c4:a9:e6:79:28:b1:ad:a9:5a:d0:94:9e:
ec:ce:3f:58:7d:46:7c:6a:d9:4e:7a:ee:eb:47:ed:
f0:04:cb:c8:f4:11:74:2a:ff:e5:22:b4:9d:d6:7e:
71:ff:7f:87:ad:4e:29:01:97:dd:85:9e:3b:87:1a:
04:99:02:2a:86:bf:1c:20:c2:6a:8f:9c:08:ce:a4:
8a:42:5a:90:8d:19:92:e5:c8:b6:ec:ac:b4:01:34:
7a:47:81:95:33:67:b4:a1:32:0a:09:d9:9b:f5:68:
88:0c:6f:d0:49:1c:36:af:95:b5:4b:51:04:ab:a3:
ca:49:ed:b9:35:fc:20:b9:9c:64:0f:cc:e6:7f:1e:
2d:a3
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
68:07:4c:1f:c3:dc:73:43:f5:24:06:1c:cd:00:ce:59:9c:77:
65:92:20:29:e9:a1:d6:3b:c3:91:58:7e:e8:ca:84:32:9f:87:
0a:8b:37:a5:bf:11:25:9e:fe:a7:69:97:68:f3:76:33:3a:67:
b5:86:41:cd:3c:09:47:2a:3c:59:26:0b:7d:91:d7:bb:27:2d:
6c:2d:c5:db:f2:0a:8a:3c:ba:c0:36:45:42:77:20:19:1e:ea:
a8:bf:86:2f:bf:de:b5:19:5a:75:78:e1:3e:be:36:ea:4d:a3:
22:4b:24:a7:5a:86:ed:4e:a6:41:5f:23:23:c2:1c:db:95:7b:
6a:89:87:9d:ed:e5:44:19:2c:bc:44:2b:66:da:dd:41:08:43:
80:e3:bb:3a:2b:cf:87:0a:ec:32:c4:b6:1c:3c:e5:00:e7:ee:
d7:b4:6f:10:93:af:cd:e0:a6:c4:da:43:5f:5c:32:08:b6:73:
bc:6d:fd:e7:1d:b8:eb:92:e5:08:45:c0:ea:bb:1c:87:9f:8c:
45:be:97:dd:bb:48:c2:39:b7:1f:56:a7:6d:a3:d7:a0:07:ab:
67:05:33:91:f6:d3:16:f0:de:be:d4:72:2e:7d:3c:25:da:e8:
cb:d7:97:6d:1a:46:ef:d4:cf:dc:e1:81:16:e7:de:34:2b:34:
1b:99:cf:b4
(8)給從服務器頒發CA證書
[root@centos7ssl]#openssl x509 -req -in slave.csr -CA cacert.pem -CAkey cakey.pem -set_serial 01 > slave.crt Signature ok subject=/C=CN/ST=beijing/L=beijing/O=magedu/OU=devops/CN=slave.magedu.com Getting CA Private Key
(9)在A主服務器驗證頒發證書的有效性
[root@centos7ssl]#openssl verify -CAfile cacert.pem master.crt slave.crt master.crt: OK slave.crt: OK
(10)在B和C從服務器上分別創建ssl文件,並在A主服務器遠程復制當前的證書文件
[root@centos777~]#mkdir /etc/my.cnf.d/ssl 在從服務器上新建ssl文件 [root@centos7ssl]#scp cacert.pem slave.crt slave.key 192.168.34.102:/etc/my.cnf.d/ssl/ 主服務器上遠程復制到B從服務器上 root@192.168.34.102's password: cacert.pem 100% 1330 354.2KB/s 00:00 slave.crt 100% 1204 547.1KB/s 00:00 slave.key 100% 1704 384.6KB/s 00:00 [root@centos7ssl]#scp cacert.pem slave.crt slave.key 192.168.34.103:/etc/my.cnf.d/ssl/ 主服務器遠程復制到C從服務器上 cacert.pem 100% 1330 719.5KB/s 00:00 slave.crt 100% 1204 592.7KB/s 00:00 slave.key 100% 1704 338.3KB/s 00:00
(11)在A主服務器上查看msyql數據庫證書文件信息,此時加密部分為空,沒有加密
MariaDB [(none)]> show variables like '%ssl%'; +---------------+----------+ | Variable_name | Value | +---------------+----------+ | have_openssl | DISABLED | | have_ssl | DISABLED | | ssl_ca | | | ssl_capath | | | ssl_cert | | | ssl_cipher | | | ssl_key | | +---------------+----------+
(12)在A主服務器的mysql數據庫中添加配置文件,保存配置文件
vim /etc/my.cnf
[mysqld]
server-id=1
log_bin=/data/logbin/mysql-bin
binlog_format=ROW
ssl-ca=/etc/my.cnf.d/ssl/cacert.pem ssl-cert=/etc/my.cnf.d/ssl/master.crt ssl-key=/etc/my.cnf.d/ssl/master.key
重啟mysql服務:
systemctl restart mariadb
(13)此時查看,證書信息,已經支持了加密
MariaDB [(none)]> show variables like '%ssl%';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 2
Current database: *** NONE ***
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /etc/my.cnf.d/ssl/cacert.pem | | ssl_capath | | | ssl_cert | /etc/my.cnf.d/ssl/master.crt | | ssl_cipher | | | ssl_key | /etc/my.cnf.d/ssl/master.key |
+---------------+------------------------------+
(14)創建一個新的賬號,並賦予復制權限,此時創建的用戶只能用加密方式登錄
MariaDB [(none)]> grant replication slave on *.* to rplssl@'192.168.34.%' identified by 'centos' require ssl;
(15)此時,我們可以在B從服務器通過驗證CA證書進行登錄創建的rplssl賬號
--ssl-ca=/etc/my.cnf.d/ssl/cacert.pem 驗證從服務器CA證書的文件 --ssl-cert=/etc/my.cnf.d/ssl/slave.crt 驗證從服務器的證書文件 --ssl-key=/etc/my.cnf.d/ssl/slave.key 驗證從服務器的私鑰文件
[root@centos777~]#mysql -urplssl -pcentos -h192.168.34.101 --ssl-ca=/etc/my.cnf.d/ssl/cacert.pem --ssl-cert=/etc/my.cnf.d/ssl/slave.crt --ssl-key=/etc/my.cnf.d/ssl/slave.key Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 6 Server version: 5.5.60-MariaDB MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>
驗證基於mysql加密的主從復制
(1)將B和C從服務器上先停掉之前的slave,並清除slave數據
stop slave; reset slave all;
(2)查看A主服務器此時的二進制日志文件大小,此時最近的是410
MariaDB [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 7396 | | mysql-bin.000002 | 729 | | mysql-bin.000003 | 618 | | mysql-bin.000004 | 264 | | mysql-bin.000005 | 410 | +------------------+-----------+
(3)在B和C從服務器上開始打開復制線程並開啟ssl加密路徑,
或者將以下路徑存在/etc/my.cnf配置文件中,重啟數據庫也可以。
/etc/my.cnf.d/ssl/cacert.pem
/etc/my.cnf.d/ssl/master.crt
/etc/my.cnf.d/ssl/master.key
[root@centos7 ~]# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 5.5.64-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.34.101',
-> MASTER_USER='rplssl',
-> MASTER_PASSWORD='centos',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000005',
-> MASTER_LOG_POS=410,
-> MASTER_SSL=1, # 加密編號
-> MASTER_SSL_CA = '/etc/my.cnf.d/ssl/cacert.pem',
-> MASTER_SSL_CERT = '/etc/my.cnf.d/ssl/slave.crt',
-> MASTER_SSL_KEY = '/etc/my.cnf.d/ssl/slave.key';
(4)在B從服務器開啟slave,並查看slave狀態
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rplssl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 410
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 694
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
(5)在C從服務器開啟slave,並查看slave狀態
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.34.101
Master_User: rplssl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 410
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 694
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
(6)在A主服務器插入一個文件,驗證復制效果。
MariaDB [(none)]> insert teachers(name)value('wang');
ERROR 1046 (3D000): No database selected
MariaDB [(none)]> use hellodb
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
MariaDB [hellodb]> insert teachers(name)value('wang');
Query OK, 1 row affected, 1 warning (0.01 sec)
MariaDB [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | a | 0 | NULL |
| 6 | biu | 0 | NULL |
| 7 | mage | 0 | NULL |
| 8 | wang | 0 | NULL |
+-----+---------------+-----+--------+
(7)查看B和C從服務器的復制結果,兩個從服務器都已將teachers表中的wang復制過去
MariaDB [(none)]> use hellodb 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 MariaDB [hellodb]> select * from teachers; +-----+---------------+-----+--------+ | TID | Name | Age | Gender | +-----+---------------+-----+--------+ | 1 | Song Jiang | 45 | M | | 2 | Zhang Sanfeng | 94 | M | | 3 | Miejue Shitai | 77 | F | | 4 | Lin Chaoying | 93 | F | | 5 | a | 0 | NULL | | 6 | biu | 0 | NULL | | 7 | mage | 0 | NULL | | 8 | wang | 0 | NULL | +-----+---------------+-----+--------+
復制的監控和維護
(1) 清理日志
PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
RESET MASTER 清空二進制日志,盡量不要使用
RESET SLAVE 清空slave
(2) 復制監控
SHOW MASTER STATUS 查看master狀態 SHOW BINLOG EVENTS 查看詳細的二進制日志 SHOW BINARY LOGS 查看日志文件 SHOW SLAVE STATUS 查看slave的狀態 SHOW PROCESSLIST 查看增加文件情況
(3) 從服務器是否落后於主服務,可能是mysql設計缺陷問題導致,主服務器的壓力很大,無法及時調度到從服務器,導致從服務器無法復制。
Seconds_Behind_Master: 0
(4) 如何確定主從節點數據是否一致
percona-tools
(5) 數據不一致如何修復:刪除從服務器的數據庫,將主服務器的數據進行完全備份,然后導入到從服務器,以主服務器最新的二進制日志開始復制。
刪除從數據庫,重新復制
示例:清理指定的二進制日志
MariaDB [hellodb]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 7396 | | mysql-bin.000002 | 729 | | mysql-bin.000003 | 618 | | mysql-bin.000004 | 264 | | mysql-bin.000005 | 604 | +------------------+-----------+ 5 rows in set (0.00 sec) MariaDB [hellodb]> purge master logs to 'mysql-bin.000005'; #清理5之前的二進制日志文件 Query OK, 0 rows affected (0.01 sec) MariaDB [hellodb]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000005 | 604 | +------------------+-----------+

