基礎環境
基于centOS7-MySQL8.0.35版本
我們先準備一臺主服務器兩臺從服務器來實現我們主從同步的訴求
Master:192.168.75.142
slave1:192.168.75.143
slave:192.168.75.145
binlog主從同步
主庫配置
#我們需要在主從庫中都需要添加server_id,每個庫的server_id都不唯一
[root@localhost ~]# tail -1 /etc/my.cnf
server_id=1
#重啟mysql服務讓配置分件生效
[root@localhost ~]# systemctl restart mysqld
#備份:
[root@localhost ~]# mysqldump --opt -B -u root -p school school1> school.sql
#授權用戶:
mysql> create user rep@'192.168.75.%' identified with mysql_native_password by 'Mhn@2001';
mysql> grant replication slave on *.* to rep@'192.168.75.%';
從庫配置
[root@localhost ~]# tail -1 /etc/my.cnf
server_id=2
[root@localhost ~]# systemctl restart mysqld[root@localhost ~]# tail -1 /etc/my.cnf
server_id=3
[root@localhost ~]# systemctl restart mysqld#還原主庫備份,到從服務器家目錄下:
scp db.sql 192.168.75.143:/root/
scp db.sql 192.168.75.145:/root/#在兩臺從主機上將復制的備份文件導入數據庫
mysql -uroot -pMysql@123 < school.sql#主庫查看
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 679 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)從庫配置
change master to
master_host='192.168.75.42',
master_user='rep',
master_password='Mhn@2001',
master_log_file='mysql-bin.000001',
master_log_pos=679,
get_master_public_key=1;
mysql> show slave status \G
*************************** 1. row ***************************Slave_IO_State: Waiting for source to send eventMaster_Host: 192.168.75.142Master_User: repMaster_Port: 3306Connect_Retry: 60Master_Log_File: binlog.000002Read_Master_Log_Pos: 694Relay_Log_File: localhost-relay-bin.000002Relay_Log_Pos: 323Relay_Master_Log_File: binlog.000002Slave_IO_Running: YesSlave_SQL_Running: Yes
從這里可以查看到狀態沒有問題可以進行主從同步
其他可選配置
#[可選] 0(默認)表示讀寫(主機),1表示只讀(從機)
read-only=0
#設置日志文件保留的時長,單位是秒
binlog_expire_logs_seconds=6000
#控制單個二進制日志大小。此參數的最大和默認值是1GB
max_binlog_size=200M
#[可選]設置不要復制的數據庫
binlog-ignore-db=test
#[可選]設置需要復制的數據庫,默認全部記錄。
binlog-do-db=需要復制的主數據庫名字
#[可選]設置binlog格式
binlog_format=STATEMENT
素材
數據庫備份,數據庫為school,素材如下1.創建student和score表CREATE TABLE student (
id INT(10) NOT NULL UNIQUE PRIMARY KEY ,
name VARCHAR(20) NOT NULL ,
sex VARCHAR(4) ,
birth YEAR,
department VARCHAR(20) ,
address VARCHAR(50)
);創建score表。SQL代碼如下:CREATE TABLE score (
id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT ,
stu_id INT(10) NOT NULL ,
c_name VARCHAR(20) ,
grade INT(10)
);2.為student表和score表增加記錄向student表插入記錄的INSERT語句如下:INSERT INTO student VALUES( 901,'張老大', '男',1985,'計算機系', '北京市海淀區');
INSERT INTO student VALUES( 902,'張老二', '男',1986,'中文系', '北京市昌平區');
INSERT INTO student VALUES( 903,'張三', '女',1990,'中文系', '湖南省永州市');
INSERT INTO student VALUES( 904,'李四', '男',1990,'英語系', '遼寧省阜新市');
INSERT INTO student VALUES( 905,'王五', '女',1991,'英語系', '福建省廈門市');
INSERT INTO student VALUES( 906,'王六', '男',1988,'計算機系', '湖南省衡陽市');向score表插入記錄的INSERT語句如下:
INSERT INTO score VALUES(NULL,901, '計算機',98);
INSERT INTO score VALUES(NULL,901, '英語', 80);
INSERT INTO score VALUES(NULL,902, '計算機',65);
INSERT INTO score VALUES(NULL,902, '中文',88);
INSERT INTO score VALUES(NULL,903, '中文',95);
INSERT INTO score VALUES(NULL,904, '計算機',70);
INSERT INTO score VALUES(NULL,904, '英語',92);
INSERT INTO score VALUES(NULL,905, '英語',94);
INSERT INTO score VALUES(NULL,906, '計算機',90);
INSERT INTO score VALUES(NULL,906, '英語',85);
create database school;
use school;
CREATE TABLE `Student` (`Sno` int(10) NOT NULL COMMENT '學號', `Sname` varchar(16) NOT NULL COMMENT '姓名',`Ssex` char(2) NOT NULL COMMENT '性別', `Sage` tinyint(2) NOT NULL DEFAULT '0' COMMENT '學生年齡',`Sdept` varchar(16) DEFAULT 'NULL' COMMENT '學生所在系別', PRIMARY KEY (`Sno`)) ;
INSERT INTO `Student` VALUES (1, '陸亞', '男', 24, '計算機網絡'),(2, 'tom', '男', 26, '英語'),(3, '張陽', '男', 21, '物流管理'), (4, 'alex', '女', 22, '電子商務');
gtid主從同步
GTID的工作原理:
1.當一個事務在主庫端執行并提交時,產生GTID,一同記錄到binlog日志中。
2.binlog傳輸到slave,并存儲到salve的relaylog后,讀取這個GTID的這個值設置GTID——next變量,即告訴slave,下一個要執行的GTID值。
3.sql線程從relaylog中獲取GTID,然后對比slave端的binlog是否有該GTID。
4.如果有記錄說明該GTID的事務已經執行,slave會忽略。
5.如果沒有記錄,slave會執行該GTID事務,并記錄到該GTID到自身的binlog,在讀取該事務前會檢查其他session持有該GTID,確保不被重復執行。
6.在解析過程中會判斷是否有主鍵,如果沒有就用二級索引,如果有就用全部掃描。
主庫配置
主庫配置
[root@localhost ~]# vim /etc/my.cnf
server_id=1
gtid_mode=ON #開啟gtid模式
enforce-gtid-consistency=ON #強制gtid一致性,開啟后對特定的create table不支持
log-bin=mysql-bin #開啟二進制日志
log-slave-updates=1 #從庫binlog記錄主庫同步的操作日志
skip-slave-start=1 #跳過slave復制線程#重啟服務
[root@localhost ~]# systemctl restart mysqld
#查看服務狀態
[root@localhost ~]# systemctl status mysqld
● mysqld.service - MySQL ServerLoaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)Active: active (running) since 四 2024-02-29 11:04:01 CST; 37min agoDocs: man:mysqld(8)http://dev.mysql.com/doc/refman/en/using-systemd.htmlProcess: 3740 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)Main PID: 3770 (mysqld)Status: "Server is operational"Tasks: 40CGroup: /system.slice/mysqld.service└─3770 /usr/sbin/mysqld[root@localhost ~]# mysql -uroot -pMysql@123
mysql> show variables like '%gtid%';
+----------------------------------+------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed | ff800e4d-d478-11ee-83a4-000c29b35fbd:1-8 |
| gtid_executed_compression_period | 0 |
| gtid_mode | ON |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+------------------------------------------+
9 rows in set (0.01 sec)
從庫配置
#slave1
server_id=2
gtid_mode=ON
enforce-gtid-consistency=ON
log-bin=mysql-bin
log-slave-updates=1
skip-slave-start=1
mysql> show variables like '%gtid%';
+----------------------------------+------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed | ff800e4d-d478-11ee-83a4-000c29b35fbd:1-8 |
| gtid_executed_compression_period | 0 |
| gtid_mode | ON |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+------------------------------------------+
9 rows in set (0.00 sec)#slave2
server_id=3
gtid_mode=ON
enforce-gtid-consistency=ON
log-bin=mysql-bin
log-slave-updates=1
skip-slave-start=1
mysql> show variables like '%gtid%';
+----------------------------------+------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed | ff800e4d-d478-11ee-83a4-000c29b35fbd:1-8 |
| gtid_executed_compression_period | 0 |
| gtid_mode | ON |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+------------------------------------------+
9 rows in set (0.00 sec)
開啟主從同步
#主庫
mysql> stop slave;
Query OK, 0 rows affected, 2 warnings (0.01 sec)mysql> create user rep@'192.168.75.%' identified with mysql_native_password by 'Mhn@2001';
Query OK, 0 rows affected (0.04 sec)mysql> grant replication slave on *.* to rep@'192.168.75.%';
Query OK, 0 rows affected (0.00 sec)
#從庫,兩個都一樣
mysql> CHANGE MASTER TO-> MASTER_HOST = '192.168.75.142',-> MASTER_USER = 'rep',-> MASTER_PASSWORD = 'Mhn@2001',-> MASTER_AUTO_POSITION = 1;
Query OK, 0 rows affected, 7 warnings (0.01 sec)
#主庫建立數據庫
mysql> create database book;
Query OK, 1 row affected (0.00 sec)mysql> use book;
Database changed
mysql> CREATE TABLE books (name char(66),price int,pages int);
'80','666');
INSERT INTO books(name,price,pages) VALUES('Artificial Intelligence','166','666');Query OK, 0 rows affected (0.02 sec)mysql> INSERT INTO books(name,price,pages) VALUES('Linux','30','666');
Query OK, 1 row affected (0.01 sec)mysql> INSERT INTO books(name,price,pages) VALUES('Cloud Computing','60','666');
Query OK, 1 row affected (0.01 sec)mysql> INSERT INTO books(name,price,pages) VALUES('Operation System','80','666');
Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO books(name,price,pages) VALUES('Artificial Intelligence','166','666');
Query OK, 1 row affected (0.00 sec)mysql> select * from books;
+-------------------------+-------+-------+
| name | price | pages |
+-------------------------+-------+-------+
| Linux | 30 | 666 |
| Cloud Computing | 60 | 666 |
| Operation System | 80 | 666 |
| Artificial Intelligence | 166 | 666 |
+-------------------------+-------+-------+
4 rows in set (0.00 sec)
#從庫的狀態查看
#slave1
mysql> show slave status \G
*************************** 1. row ***************************Slave_IO_State: Waiting for source to send eventMaster_Host: 192.168.75.142Master_User: repMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000001Read_Master_Log_Pos: 680Relay_Log_File: localhost-relay-bin.000002Relay_Log_Pos: 896Relay_Master_Log_File: mysql-bin.000001Slave_IO_Running: YesSlave_SQL_Running: Yes
#slave2
mysql> show slave status \G
*************************** 1. row ***************************Slave_IO_State: Waiting for source to send eventMaster_Host: 192.168.75.142Master_User: repMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000001Read_Master_Log_Pos: 680Relay_Log_File: localhost-relay-bin.000002Relay_Log_Pos: 896Relay_Master_Log_File: mysql-bin.000001Slave_IO_Running: YesSlave_SQL_Running: Yes
#從庫查看
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| book |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)mysql> use book;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;
+----------------+
| Tables_in_book |
+----------------+
| books |
+----------------+
1 row in set (0.00 sec)mysql> select * from book.books;
+-------------------------+-------+-------+
| name | price | pages |
+-------------------------+-------+-------+
| Linux | 30 | 666 |
| Cloud Computing | 60 | 666 |
| Operation System | 80 | 666 |
| Artificial Intelligence | 166 | 666 |
+-------------------------+-------+-------+
4 rows in set (0.00 sec)
主庫
從庫1
從庫2
可以看到最后的gtid值都一樣這就說明我們配置完成。
解決問題
在gtid配置中如果出現?Last_IO_Error: Error connecting to source 'root@192.168.75.142:3306'. This was attempt 1/86400, with a delay of 60 seconds between attempts. Message: Host '192.168.75.143' is not allowed to connect to this MySQL server
可以嘗試更改一下主庫的mysql> ?create user rep@'192.168.75.%' identified with mysql_native_password by 'Mhn@2001';
Query OK, 0 rows affected (0.04 sec)
首先我們需要將所有的庫進行stop slave;操作,然后進行操作,修改完成后再次開啟就可以使用。
在遇到問題可以使用翻譯和查詢日志來進行查看
如果我們是使用一段時間mysql后才配置的gtid主從同步需要注意gtid值需要開始的位置,不能從1開始
需要注入空事務,從而解決起始位置相同
stop slave;
set gtid_next='gtid值:開始位置';
begin;commit;
set gtid_next='AUTOMATIC';
初始化mysql
學習過程中因為gtid數據不同步可以進行初始化mysql
在初始化之前必須要將mysql數據目錄所有內容全部清空
systemctl stop mysqld
mysql --initialize --uesr=mysql
然后重新啟動mysql
systemctl restart mysqld
進入mysql,進入后需要刷新權限表
FLUSH PRIVILEGES;
最后再修改密碼
alter user root@localhost identified by 'Mysql@123';
最后需要在配置文件中刪除--skip-grant-tables