系統環境
主機名 IP
node1 192.168.231.130
node2 192.168.231.131
MariaDB版本
# mysql --version
mysql Ver 15.1 Distrib 5.5.60-MariaDB, for Linux (x86_64) using readline 5.1
Mariadb主從複製
主只可寫,從只可讀
主從複製:
從節點:
I/O Thread:從Master請求二進制日誌事件,並保存於中繼日誌中
SQL Thread:從中繼日誌中讀取日誌文件,在本地完成重放
主節點:
dump Thread:爲每個Slave的I/O Thread啓動一個dump線程,用於向其發送binary log events
特點:
1.異步複製
2.主從數據不一致比較常見
配置過程:
主節點:
(1)啓動二進制日誌
(2)爲當前節點設置一個全局唯一的ID號
(3)創建有複製權限的用戶賬號
從節點:
(1)啓動中繼日誌
(2)爲當前節點設置一個全局唯一的ID號
(3)使用有複製權限的用戶賬號連接至主服務器,並啓動複製線程
實例
#編輯node1配置文件
[root@node1 ~]# vim /etc/my.cnf
log_bin=mysql-bin #開啓二進制日誌,以mysql-bin命名文件
innodb_file_per_table=ON #每個新創建的表都會有一個表空間,將每個新創建的表的數據及索引存儲在一個獨立的.ibd文件裏
server_id=1 #id號
skip_name_resolve=ON #禁止域名解析的
#修改配置文件後重啓mariadb
[root@node1 ~]# systemctl restart mariadb
#創建repluser用戶,並賦予REPLICATION SLAVE,REPLICATION CLIENT權限
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.231.131' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.01 sec)
- REPLICATION SLAVE :常用於建立複製時所需要用到的用戶權限,也就是slave server必須被master server授權具有該權限的用戶,才能通過該用戶複製。
- REPLICATION CLIENT :不可用於建立複製,有該權限時,只是多了可以使用如"SHOW SLAVE STATUS"、"SHOW MASTER STATUS"等命令。
#刷新權限
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
#編輯node2的mariadb配置文件
[root@node2 ~]# vim /etc/my.cnf
relay_log=relay-log #中繼日誌
server_id=6
innodb_file_per_table=ON
skip_name_resolve=ON
[root@node2 ~]# systemctl start mariadb
[root@node1 mysql]# mysql
MariaDB [(none)]> help CHANGE MASTER TO
#查看主節點二進制日誌
MariaDB [(none)]> show master logs;
+-------------------+-----------+
| Log_name | File_size |
+-------------------+-----------+
| master-bin.000001 | 30331 |
| master-bin.000002 | 1038814 |
| master-bin.000003 | 245 |
+-------------------+-----------+
3 rows in set (0.00 sec)
[root@node2 mysql]# mysql
#查看CHANGE MASTER TO 詳細解釋
MariaDB [(none)]> help CHANGE MASTER TO
#確定需要同步的主機IP,用戶名,密碼,binlog文件,binlog位置等信息
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.231.130',MASTER_USER='repluser',MASTER_PASSWORD='123456',MASTER_LOG_FILE='master-bin.000003',MASTER_LOG_POS=245;
#查看slave的狀態
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.231.130
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000003 #當前二進制日誌
Read_Master_Log_Pos: 245 #二進制記錄位置
Relay_Log_File: relay-log.000001 #中繼日誌
Relay_Log_Pos: 4
Relay_Master_Log_File: master-bin.000003
Slave_IO_Running: No #IO線程沒有開啓
Slave_SQL_Running: No #SQL線程沒有開啓
#啓動SLAVE,相應的IO和SQL線程就會開啓
MariaDB [(none)]> START SLAVE;
測試:
#創建數據庫後,二進制日誌進行記錄,位置變爲578
[root@node1 ~]# mysql
MariaDB [(none)]> create database mydb;
MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000003 | 578 | | |
+-------------------+----------+--------------+------------------+
[root@node2 ~]# mysql
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.231.130
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000003
Read_Master_Log_Pos: 578 #讀取node1二進制日誌到578,說明覆製成功
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 863
Relay_Master_Log_File: master-bin.000003
Slave_IO_Running: Yes #IO線程開啓
Slave_SQL_Running: Yes #SQL線程開啓
#node2也可查看到mydb數據庫
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| performance_schema |
| test |
+--------------------+
注意:進行下邊實驗時,數據可能會影響,可刪除/etc/my.cnf中datadir目錄中數據,並重啓mariadb
MariaDB主主複製
都可進行讀寫
互爲主從:
1、數據不一致:因此,慎用
2、自動增長id
需要用到輔助工具(這裏不再使用奇偶id,使用自增id即可)
否則會出現:
| 12 | landongyang |
| 14 | ruifeng |
| 16 | xiaohe |
| 17 | lisiye |
| 19 | changshun |
| 21 | lidaniang |
| 23 | wenxiansheng |
| 24 | landongyang1 |
| 26 | ruifeng1 |
| 28 | xiaohe1 |
配置一個節點使用奇數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)均把對方指定爲主節點,並啓動複製線程
實例
#編輯node1配置文件
[root@node1 ~]# vim /etc/my.cnf
log_bin=master-bin
relay_log=relay-log
innodb_file_per_table=ON
server_id=1
skip_name_resolve=ON
#重啓mariadb
[root@node1 ~]# systemctl restart mariadb
[root@node1 ~]# mysql
#下邊命令不再註釋,可看前文
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.231.131' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000003 | 499 | | |
+-------------------+----------+--------------+------------------+
#編輯node2配置文件
[root@node2 ~]# vim /etc/my.cnf
log_bin=master-bin
relay_log=relay-log
innodb_file_per_table=ON
server_id=1
skip_name_resolve=ON
#重啓mariadb
[root@node2 ~]# systemctl start mariadb
[root@node2 ~]# mysql
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.231.130' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000003 | 509 | | |
+-------------------+----------+--------------+------------------+
[root@node1 ~]# mysql
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.231.131',MASTER_USER='repluser',MASTER_PASSWORD='123456',MASTER_LOG_FILE='master-bin.000003',MASTER_LOG_POS=509;
MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000003 | 499 | | |
+-------------------+----------+--------------+------------------+
[root@node2 ~]# mysql
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.231.130',MASTER_USER='repluser',MASTER_PASSWORD='123456',MASTER_LOG_FILE='master-bin.000003',MASTER_LOG_POS=499;
Query OK, 0 rows affected (0.02 sec)
MariaDB [(none)]> start slave;
[root@node1 ~]# mysql
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.231.131
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000003
Read_Master_Log_Pos: 509
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 530
Relay_Master_Log_File: master-bin.000003
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: 509
Relay_Log_Space: 818
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: 6
1 row in set (0.00 sec)
[root@node2 ~]# mysql
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.231.130
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000003
Read_Master_Log_Pos: 509
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 530
Relay_Master_Log_File: master-bin.000003
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: 509
Relay_Log_Space: 818
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
1 row in set (0.00 sec)
測試
node1和node2都可進行讀寫
#進入數據庫創建數據庫
[root@node1 ~]# mysql
MariaDB [(none)]> create database mydb;
MariaDB [(none)]> use mydb
MariaDB [mydb]> create table student(id int NOT NULL AUTO_INCREMENT PRIMARY KEY,name char(20));
MariaDB [mydb]> insert into student(name) values('changshun'),('lidaniang'),('wenxiansheng');
MariaDB [mydb]> select * from student;
+----+--------------+
| id | name |
+----+--------------+
| 1 | changshun |
| 2 | lidaniang |
| 3 | wenxiansheng |
+----+--------------+
[root@node2 ~]# mysql
MariaDB [(none)]> use mydb;
MariaDB [mydb]> select * from student;
+----+--------------+
| id | name |
+----+--------------+
| 1 | changshun |
| 2 | lidaniang |
| 3 | wenxiansheng |
+----+--------------+
MariaDB [mydb]> insert into student(name) values('tianyou'),('ruixuan'),('xiaoshun');
MariaDB [mydb]> select * from student;
+----+--------------+
| id | name |
+----+--------------+
| 1 | changshun |
| 2 | lidaniang |
| 3 | wenxiansheng |
| 4 | tianyou |
| 5 | ruixuan |
| 6 | xiaoshun |
+----+--------------+
MariaDB半同步複製
主只可讀,從只可讀
首先了解一下半同步複製
- 異步複製(Asynchronous replication)
MySQL默認的複製即是異步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從數據庫是否已經接收並處理,這樣就會有一個問題,主服務如果crash掉了,此時主服務上已經提交的事務可能並沒有傳到從上,如果此時,強行將從提升爲主,可能導致新主上的數據不完整。
- 全同步複製(Fully synchronous replication)
指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因爲需要等待所有從庫執行完該事務才能返回,所以全同步複製的性能必然會收到嚴重的影響。
- 半同步複製(Semisynchronous replication)
介於異步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於異步複製,半同步複製提高了數據的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網絡中使用。
master:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SET GLOBAL VARIABLES rpl_semi_sync_master_enabled=l;
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';
mysq1> SHOW GLOBAL STATUS LIKE '%semi%';
slave:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL VARIABLES rpl_semi_sync_slave_enabled=1;
#編輯node1配置文件
[root@node1 ~]# vim /etc/my.cnf
log_bin=master-bin
innodb_file_per_table=ON
server_id=1
skip_name_resolve=ON
#重啓mariadb
[root@node1 ~]# systemctl restart mariadb
[root@node1 ~]# mysql
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.231.131' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
#查看當前二進制日誌
MariaDB [(none)]> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000003 | 499 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
#在node1安裝semisync_master,主半同步插件
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#查看插件列表中是否已安裝
MariaDB [(none)]> SHOW PLUGINS;
| rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL |
#查看半同步複製相關變量
MariaDB [(none)]> show global variables like '%semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
+------------------------------------+-------+
#開啓半同步複製功能
MariaDB [(none)]> set global rpl_semi_sync_master_enabled=1;
MariaDB [(none)]> show global variables like '%semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
+------------------------------------+-------+
#編輯node2配置文件
[root@node2 ~]# vim /etc/my.cnf
relay_log=relay-log
server_id=6
innodb_file_per_table=ON
skip_name_resolve=ON
[root@node2 ~]# systemctl restart mariadb
[root@node2 ~]# mysql
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
| rpl_semi_sync_slave | ACTIVE | REPLICATION | semisync_slave.so | GPL |
MariaDB [(none)]> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
MariaDB [(none)]> set global rpl_semi_sync_slave_enabled=1;
MariaDB [(none)]> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
[root@node2 ~]# mysql
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.231.130',MASTER_USER='repluser',MASTER_PASSWORD='123456',MASTER_LOG_FILE='master-bin.000003',MASTER_LOG_POS=499;
Query OK, 0 rows affected (0.01 sec)
MariaDB [(none)]> start slave;
測試
[root@node1 ~]# mysql
MariaDB [(none)]> create database mydb;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> use mydb;
Database changed
MariaDB [mydb]> create table mytb(id int,name char(30));
Query OK, 0 rows affected (0.01 sec)
MariaDB [mydb]> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 1074 |#平均等待時間
| Rpl_semi_sync_master_net_wait_time | 2149 |#半同步複製等待時間
| Rpl_semi_sync_master_net_waits | 2 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 1031 |
| Rpl_semi_sync_master_tx_wait_time | 2063 |
| Rpl_semi_sync_master_tx_waits | 2 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 2 |
+--------------------------------------------+-------+
複製過濾
複製過濾器:
讓從節點僅複製指定的數據庫,或指定數據庫的指定表
有兩種實現方式:
(1)主服務器僅向二進制日誌中記錄與特定數據庫(特定表)相關的事件
問題:時間還原無法實現;不建議使用
參數:
binlog_do_db= #數據庫白名單列表
binlog_ignore_db= #數據庫黑名單列表
(2)從服務器SQL_THREAD在replay中繼日誌中的事件時,僅讀取與特定數據庫(特定表)相關的事件並應用於本地
問題:會造成網絡及IO浪費
參數:
replicate_do_db
replicate_ignore_db
replicate_do_table
replicate_ignore_db
replicate_ignore_table
replicate_wild_do_table
replicate_wild_ignore_table
在這裏演示第二種方案:
可以基於半同步複製進行實驗,只是設置參數進行過濾
[root@node2 ~]# mysql
#先把slave停掉,再設置變量,否則會報錯
MariaDB [(none)]> stop slave;
MariaDB [(none)]> show global 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 | |
+----------------------------------+-----------+
#設置複製的數據庫白名單
MariaDB [(none)]> set global replicate_do_db=mydb;
MariaDB [(none)]> start slave;
測試
node1:
MariaDB [mydb]> create database yourdb;
MariaDB [mydb]> insert into mytb values(1,'ruixuan'),(2,'ruifeng'),(3,'ruiquan');
MariaDB [mydb]> select * from mytb;
+------+---------+
| id | name |
+------+---------+
| 1 | ruixuan |
| 2 | ruifeng |
| 3 | ruiquan |
+------+---------+
node2:
#沒有複製yourdb
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| performance_schema |
| test |
+--------------------+
#數據複製到mydb中的表mytb
MariaDB [mydb]> select * from mytb;
+------+---------+
| id | name |
+------+---------+
| 1 | ruixuan |
| 2 | ruifeng |
| 3 | ruiquan |
+------+---------+