前言
GTID(Global Transaction ID)是MySQL5.6引入的功能,可以在集羣全局範圍標識事務,用於取代過去通過binlog文件偏移量定位複製位置的傳統方式。藉助GTID,在發生主備切換的情況下,MySQL的其它Slave可以自動在新主上找到正確的複製位置,這大大簡化了複雜複製拓撲下集羣的維護,也減少了人爲設置複製位置發生誤操作的風險。另外,基於GTID的複製可以忽略已經執行過的事務,減少了數據發生不一致的風險。
本文根據GTID搭建,MySQL 5.6 後引入支持
- Replication集羣是MySQL自帶的數據同步機制
- MySQL通過讀取、執行另一個MySQL的bin_log日誌,實現數據同步
使用限制
- 無法再使用 create table … select 建立表
- 無法再事務中使用 create temporary table 建立臨時表
- 無法使用關聯更新同時更新事務表和非事務表
基本原理
具體流程
- 主庫將變更寫入到主庫的binlog中
- 從庫的IO進程讀取主庫binlog內容存儲到Relay Log日誌中
- 從庫的SQL進程讀取Relay Log日誌中內容在從庫中重放
Master 與 Slave 是單向同步的,如果我們想要雙向同步,可以讓雙方互爲主從關係
配置主從數據庫服務器參數
參數 | 說明 |
---|---|
log_bin | 啓動二進制日誌,配置路徑就爲存儲路徑 如配置 mysql-bin 那就會放入datadir 並以這個爲前綴 |
server-id | 在mysql集羣中每個id都不一致,建立建議使用服務器IP後兩段作爲ID 比如192.168.10.68 ID可以命名爲 1068 |
relay_log | 啓動 relay_log,配置路徑就爲存儲路徑 如配置 relay-bin 那就會放入datadir 並以這個爲前綴 |
relay_only | 不能執行寫操作的,不管有沒有 save權限,但supper用戶依舊可以,如:root 好處是:避免誤操作寫入從服務器,導致主從數據不一致 |
super_read_only | super用戶也不可以執行寫操作,Mysql>=5.7 |
skip_slave_start | 在slave服務器重啓後,不會自動啓動複製鏈路 正常情況我們需要檢查沒有問題後,手動啓動 |
master_info_repository | 存儲到數據庫表中 |
relay_log_info_repository | 將主從同步的信息,存儲到innodb的表中 |
流程
-
主節點必須開啓binlog日誌,主從節點都要開啓server_id
-
主節點的同步賬號必須具有reload、super、replication slave 權限
-
主從節點的配置文件都要開啓GTID,否則無法利用延時節點找回數據
[mysqld] log_bin = mysql-bin server-id = 10565 gtid_mode = on enforce-gtid-consistency log-slave-updates = on
-
從節點必須開啓 relay_log 日誌
[mysqld] log_bin = mysql-bin server-id = 10566 # gtid gtid_mode = on enforce-gtid-consistency log-slave-updates = on relay_log = relay-bin
-
slave打開只讀屬性,避免程序誤寫入,導致主從失效
read_only = on super_read_only = on
環境配置
環境說明
主機名 | IP | 角色 |
---|---|---|
docker-master | 192.168.105.65 | Master |
docker-slave | 192.168.105.66 | Slave |
mysql配置文件 my.cnf
vim my.cnf
[client]
socket = /var/run/mysqld/mysqld.sock
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/datadir
basedir = /var/lib/mysql
log_bin = mysql-bin
relay_log = relay-bin
server-id = 1111
# 數據字符集
character_set_server = utf8
# 允許遠程訪問的IP地址
bind-address = 0.0.0.0
# 跳過DNS解析
skip-name-resolve
symbolic-links= 0
# gtid
gtid_mode = on
enforce-gtid-consistency
log-slave-updates = on
master節點
server-id = 10565
slave節點
server-id = 10566
兩個節點啓動docker
如果你還不會Docker建議學一下把,我博客也有文章
docker run -d -p 3306:3306 --name my-mysql \
-v $PWD/my.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf \
-v $PWD/db_backup:/data/db_backup \
-v $PWD/mysql:/var/lib/mysql \
-v $PWD/datadir:/var/lib/datadir \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7.27
master節點操作
登錄mysql
mysql -uroot -p123456
首先創建一個用戶
create user 'backup'@'%' identified by '123456';
進行授權
相比全量備份,多了一個 replication slave
grant select,reload,lock tables,replication slave,replication client,show view,event,process,file on *.* to 'backup'@'%';
查看
show grants for 'backup'@'%';
創建數據庫,創建測試表
create database test;
use test;
CREATE TABLE `student` (
`student_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`student_name` varchar(64) NOT NULL COMMENT '學生名字',
PRIMARY KEY (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入數據
INSERT INTO student(`student_id`, `student_name`) VALUES (1, 'A');
INSERT INTO student(`student_id`, `student_name`) VALUES (2, 'B');
INSERT INTO student(`student_id`, `student_name`) VALUES (3, 'C');
INSERT INTO student(`student_id`, `student_name`) VALUES (4, 'D');
Slave節點
登錄mysql
mysql -uroot -p123456
停止slave
stop slave;
修改鏈路
change master to
master_host='192.168.105.65',
master_port=3306,
master_user='backup',
master_password='123456',
master_auto_position = 1;
啓動
start slave;
查看鏈路狀態
show slave status \G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
等個幾秒,或者直接查看也行,看主從同步成功沒
use test;
select * from student;
+------------+--------------+
| student_id | student_name |
+------------+--------------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
+------------+--------------+
驗證主從同步
master節點,插入數據
INSERT INTO student(`student_id`, `student_name`) VALUES (5, 'E');
slave節點查詢數據
select * from student;
+------------+--------------+
| student_id | student_name |
+------------+--------------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
+------------+--------------+
Slave 節點收尾工作
退出Docker容器 如果用Docker的話
exit
加入只讀屬性,避免程序員誤寫入數據,導致主從同步失敗
vim my.cnf
[mysqld]
# 主從配置中,加入這兩個只讀屬性
read_only = on
super_read_only = on
重啓mysql 這裏說說哈,Docker你就直接重啓容器就行
service mysql restart
測試從節點是否限制插入數據
INSERT INTO student(`student_id`, `student_name`) VALUES (6, 'F');
ERROR 1290 (HY000): Unknown error 1290