一、環境準備
主機名 | ip | 操作系統 | 備注 |
---|---|---|---|
node01 | 192.168.48.91 | CentOS Linux 7 (Core) | mysql主庫 |
node01 | 192.168.48.92 | CentOS Linux 7 (Core) | mysql主庫 |
192.168.48.90 | 漂移IP(VIP) |
centos7鏡像下載地址:
https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2207-02.iso
二、安裝mysql8
node01&node02
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo yum makecache yum update systemctl disable --now firewalld setenforce 0 sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config sed -i '3 s/^/# /' /etc/chrony.conf sed -i '4 a server ntp.aliyun.com iburst' /etc/chrony.conf systemctl restart chronyd.service systemctl enable chronyd.service chronyc sources wget http://dev.mysql.com/get/mysql80-community-release-el7-8.noarch.rpm yum localinstall -y mysql80-community-release-el7-8.noarch.rpm yum repolist enabled | grep mysql yum -y install mysql-community-server --nogpgcheck rpm -qa |grep mysql systemctl start mysqld systemctl enable mysqld systemctl daemon-reload #查看mysql密碼 cat /var/log/mysqld.log | grep password #2025-08-29T05:53:37.423668Z 6 [Note] [MY-010454] [Server] A temporary password is generated for #root@localhost: Oeblh;:dK1ba #使用密碼登錄 mysql -uroot -p 'Oeblh;:dK1ba' #修改密碼 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Admin123.'; #創建遠程連接用戶 create user 'root'@'%' identified with mysql_native_password by 'Admin123.'; grant all privileges on *.* to 'root'@'%' with grant option; flush privileges;
三、mysql主主復制
流程圖:
flowchart TDA[開始配置MySQL從庫] --> B[修改從庫配置文件my.cnf]B --> C[重啟從庫MySQL服務]C --> D[創建主庫數據快照并導入從庫]D --> E[在從庫上配置主庫連接信息]E --> F[啟動從庫復制進程]F --> G[檢查從庫復制狀態]G --> H{Slave_IO_Running和<br>Slave_SQL_Running是否均為Yes?}H -->|是| I[主從復制建立成功]H -->|否| J[根據錯誤信息排查問題]J --> E
1. 修改配置文件
1.1. node01
這里開啟了GTID。
vim /etc/my.cnf
[mysqld] # 數據文件存儲目錄。MySQL所有的數據庫數據(表、索引等)都存放在這個路徑下。 datadir=/var/lib/mysql ? # MySQL服務器監聽的Unix套接字文件路徑。本地客戶端可以通過這個socket文件連接數據庫,速度比TCP/IP更快。 socket=/var/lib/mysql/mysql.sock ? # MySQL錯誤日志文件的存放路徑。啟動失敗、運行錯誤等信息都會記錄在這里,是排查問題的重要依據。 log-error=/var/log/mysqld.log ? # 存儲MySQL服務進程ID(PID)的文件路徑。系統和管理工具通過讀取這個文件來獲取MySQL的進程號。 pid-file=/var/run/mysqld/mysqld.pid ? # 服務節點ID,在復制拓撲(主從/主主)中每個實例必須具有唯一ID(1-2^32-1)。 # 主從復制中,主庫和從庫的server-id必須不同。 server-id=1 ? # 開啟二進制日志(binlog)并設置二進制日志文件的基本名。 # binlog記錄了所有更改數據的SQL語句,用于主從復制和數據恢復。 log-bin=master-bin ? # 【謹慎使用】指定需要記錄二進制日志的數據庫。只有在此列表中數據庫的更改才會被寫入binlog。 # 基于"當前USE的數據庫"進行過濾,有風險(如:在db1中更新db2的表將不會被記錄)。 # 建議使用反向過濾(binlog-ignore-db)或在從庫過濾,而非在此正向過濾。 binlog-do-db=your_database_name ? # 設置中繼日志的文件名。中繼日志存在于從庫,用于存儲從主庫binlog讀取到的數據更改事件。 relay-log=mysql-relay-bin ? # 【推薦方式】指定不記錄二進制日志的數據庫(反向過濾,更安全)。 # 通常忽略MySQL系統自帶的數據庫,避免不必要的復制。 binlog_ignore_db=sys ? ? ? ? ? ? ? # 忽略sys系統庫 binlog_ignore_db=mysql ? ? ? ? ? ? # 忽略mysql系統庫(存儲用戶權限等信息) binlog_ignore_db=information_schema # 忽略information_schema虛擬庫(存儲元數據) binlog_ignore_db=performance_schema # 忽略performance_schema虛擬庫(存儲性能指標) ? # --- 自增字段全局配置(在多主復制架構中用于避免自增ID沖突)--- # 自增字段每次增長的步長。在雙主模式下通常設置為節點的總數。 auto_increment_increment=2 # 自增字段的起始偏移量。每個實例應設置不同的偏移量(如1和2),確保ID不會沖突。 auto_increment_offset=1 ? # --- 從庫復制過濾規則(通常配置在從庫的my.cnf中,主庫配置無效)--- # 指定從庫需要復制的數據庫。與binlog-do-db類似,有基于默認數據庫過濾的風險。 # replicate_do_db=test # 指定從庫需要忽略的數據庫。 # replicate_ignore_db=mysql ? # --- 字符集與排序規則配置 --- # 設置MySQL服務器的默認字符集為utf8mb4,支持存儲所有的UTF-8字符,包括表情符號(emoji)。 character-set-server=utf8mb4 # 設置服務器默認的排序規則(collation)。utf8mb4_unicode_ci基于Unicode標準排序,精度高。 collation-server=utf8mb4_unicode_ci ? # --- 事務隔離級別 --- # 設置默認的事務隔離級別為READ-COMMITTED(讀已提交)。 # 此級別可以避免臟讀,但可能出現不可重復讀和幻讀。許多復制場景推薦使用此級別。 transaction-isolation=READ-COMMITTED ? # --- GTID(全局事務標識符)配置 --- # 開啟GTID模式。GTID為每個提交的事務生成一個全局唯一的ID,簡化了復制的維護和故障恢復。 gtid-mode=on # 強制GTID一致性,確保所有事務都可以以事務安全的方式被記錄和復制。 enforce-gtid-consistency=true ?
1.2. node02
vim /etc/my.cnf
[mysqld] # 數據文件存儲目錄。MySQL所有的數據庫數據(表、索引等)都存放在這個路徑下。 datadir=/var/lib/mysql ? # MySQL服務器監聽的Unix套接字文件路徑。本地客戶端可以通過這個socket文件連接數據庫,速度比TCP/IP更快。 socket=/var/lib/mysql/mysql.sock ? # MySQL錯誤日志文件的存放路徑。啟動失敗、運行錯誤等信息都會記錄在這里,是排查問題的重要依據。 log-error=/var/log/mysqld.log ? # 存儲MySQL服務進程ID(PID)的文件路徑。系統和管理工具通過讀取這個文件來獲取MySQL的進程號。 pid-file=/var/run/mysqld/mysqld.pid ? # 服務節點ID,在復制拓撲(主從/主主)中每個實例必須具有唯一ID(1-2^32-1)。 # 主從復制中,主庫和從庫的server-id必須不同。 server-id=2 ? # 開啟二進制日志(binlog)并設置二進制日志文件的基本名。 # binlog記錄了所有更改數據的SQL語句,用于主從復制和數據恢復。 log-bin=master-bin ? # 【謹慎使用】指定需要記錄二進制日志的數據庫。只有在此列表中數據庫的更改才會被寫入binlog。 # 基于"當前USE的數據庫"進行過濾,有風險(如:在db1中更新db2的表將不會被記錄)。 # 建議使用反向過濾(binlog-ignore-db)或在從庫過濾,而非在此正向過濾。 binlog-do-db=your_database_name ? # 設置中繼日志的文件名。中繼日志存在于從庫,用于存儲從主庫binlog讀取到的數據更改事件。 relay-log=mysql-relay-bin ? # 【推薦方式】指定不記錄二進制日志的數據庫(反向過濾,更安全)。 # 通常忽略MySQL系統自帶的數據庫,避免不必要的復制。 binlog_ignore_db=sys ? ? ? ? ? ? ? # 忽略sys系統庫 binlog_ignore_db=mysql ? ? ? ? ? ? # 忽略mysql系統庫(存儲用戶權限等信息) binlog_ignore_db=information_schema # 忽略information_schema虛擬庫(存儲元數據) binlog_ignore_db=performance_schema # 忽略performance_schema虛擬庫(存儲性能指標) ? # --- 自增字段全局配置(在多主復制架構中用于避免自增ID沖突)--- # 自增字段每次增長的步長。在雙主模式下通常設置為節點的總數。 auto_increment_increment=2 # 自增字段的起始偏移量。每個實例應設置不同的偏移量(如1和2),確保ID不會沖突。 auto_increment_offset=2 ? # --- 從庫復制過濾規則(通常配置在從庫的my.cnf中,主庫配置無效)--- # 指定從庫需要復制的數據庫。與binlog-do-db類似,有基于默認數據庫過濾的風險。 # replicate_do_db=test # 指定從庫需要忽略的數據庫。 # replicate_ignore_db=mysql ? # --- 字符集與排序規則配置 --- # 設置MySQL服務器的默認字符集為utf8mb4,支持存儲所有的UTF-8字符,包括表情符號(emoji)。 character-set-server=utf8mb4 # 設置服務器默認的排序規則(collation)。utf8mb4_unicode_ci基于Unicode標準排序,精度高。 collation-server=utf8mb4_unicode_ci ? # --- 事務隔離級別 --- # 設置默認的事務隔離級別為READ-COMMITTED(讀已提交)。 # 此級別可以避免臟讀,但可能出現不可重復讀和幻讀。許多復制場景推薦使用此級別。 transaction-isolation=READ-COMMITTED ? # --- GTID(全局事務標識符)配置 --- # 開啟GTID模式。GTID為每個提交的事務生成一個全局唯一的ID,簡化了復制的維護和故障恢復。 gtid-mode=on # 強制GTID一致性,確保所有事務都可以以事務安全的方式被記錄和復制。 enforce-gtid-consistency=true
2. 重啟MySQL服務
node01&node02
sudo systemctl restart mysql
3. 創建復制用戶
在兩臺服務器上創建一個用于復制的MySQL用戶,并授予必要的權限。
node01
CREATE USER 'replication'@'192.168.48.92' IDENTIFIED WITH mysql_native_password BY 'Admin123.'; GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.48.92'; FLUSH PRIVILEGES; ? CHANGE MASTER TO MASTER_HOST='192.168.48.92', MASTER_USER='replication', MASTER_PASSWORD='Admin123.', MASTER_AUTO_POSITION=1;
node02
CREATE USER 'replication'@'192.168.48.91' IDENTIFIED WITH mysql_native_password BY 'Admin123.'; GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.48.91'; FLUSH PRIVILEGES; ? CHANGE MASTER TO MASTER_HOST='192.168.48.91', MASTER_USER='replication', MASTER_PASSWORD='Admin123.', MASTER_AUTO_POSITION=1;
4. 開啟復制
node01&node02
#開啟復制 START SLAVE; #檢查復制狀態 SHOW SLAVE STATUS \G ? #兩個節點以下參數均為yes說明復制正常。 Slave_IO_Running: Yes Slave_SQL_Running: Yes ?
重點關注以下字段:
-
Slave_IO_Running
: Yes (表示I/O線程正常運行,能從主庫讀取binlog) -
Slave_SQL_Running
: Yes (表示SQL線程正常運行,能重放中繼日志) -
Seconds_Behind_Master
: 0 (表示主從延遲為0秒。如果值不為0,說明存在延遲;如果為NULL,則需檢查錯誤)18 -
Last_IO_Error
,Last_SQL_Error
: 如果復制進程異常,這里會顯示錯誤信息
5. 驗證
node01
CREATE DATABASE IF NOT EXISTS your_database_name; USE your_database_name; ? CREATE TABLE node01 (id INT AUTO_INCREMENT PRIMARY KEY,hostname VARCHAR(100) NOT NULL,ip_address VARCHAR(15) NOT NULL,status VARCHAR(20) DEFAULT 'active',created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,description TEXT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ? ? ? INSERT INTO node02 (hostname, ip_address, description) VALUES ('master-node', '192.168.48.92', '這是主庫節點01的測試數據,用于驗證主從復制'); ? ?
node02
USE your_database_name; SELECT * FROM node01;
成功輸出
mysql> SELECT * FROM node01; +----+-------------+---------------+--------+---------------------+---------------------+----------------------------------------------------------------+ | id | hostname ? | ip_address ? | status | created_at ? ? ? ? | updated_at ? ? ? ? | description ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | +----+-------------+---------------+--------+---------------------+---------------------+----------------------------------------------------------------+ | 1 | master-node | 192.168.48.92 | active | 2025-08-29 20:00:16 | 2025-08-29 20:00:16 | 這是主庫節點01的測試數據,用于驗證主從復制 ? ? ? ? ? ? ? ? ? ? | +----+-------------+---------------+--------+---------------------+---------------------+----------------------------------------------------------------+ 1 row in set (0.00 sec) ? ?
node02
CREATE TABLE node02 (id INT AUTO_INCREMENT PRIMARY KEY,hostname VARCHAR(100) NOT NULL,ip_address VARCHAR(15) NOT NULL,status VARCHAR(20) DEFAULT 'active',created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,description TEXT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ? ? ? INSERT INTO node02 (hostname, ip_address, description) VALUES ('master-node', '192.168.48.91', '這是主庫節點02的測試數據,用于驗證主從復制'); ?
node01
SELECT * FROM node02;
成功輸出
mysql> SELECT * FROM node02; +----+-------------+---------------+--------+---------------------+---------------------+----------------------------------------------------------------+ | id | hostname ? | ip_address ? | status | created_at ? ? ? ? | updated_at ? ? ? ? | description ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | +----+-------------+---------------+--------+---------------------+---------------------+----------------------------------------------------------------+ | 2 | master-node | 192.168.48.91 | active | 2025-08-29 20:03:52 | 2025-08-29 20:03:52 | 這是主庫節點02的測試數據,用于驗證主從復制 ? ? ? ? ? ? ? ? ? ? | +----+-------------+---------------+--------+---------------------+---------------------+----------------------------------------------------------------+ 1 row in set (0.00 sec)
到此,主主復制完成
四、配置keepalived
1. 下載keepalived
node01&node02
yum install -y keepalived
2. 編寫心跳檢測腳本
node01&node02
cat > /etc/keepalived/mysql_check.sh << 'EOF' #!/bin/bash C=`ps -C mysqld --no-header | wc -l` if [ $C -eq 0 ];thenexit 1 fi exit 0 EOF
3. 修改配置文件
node01
cat > /etc/keepalived/keepalived.conf << 'EOF' global_defs {vrrp_mcast_group4 224.0.0.18 } ? vrrp_script check_mysql {script "/etc/keepalived/mysql_check.sh" #腳本存放位置internal 2 #執行時間(周期,單位:秒) } ? vrrp_instance DB {state MASTER #這里主節點為 MASTER,其余的節點(備用節點)修改為 BACKUPinterface ens33 #網卡名稱根據實際情況修改virtual_router_id 51#同一組高可用集群中的所有節點必須設置相同的 ID,不同集群必須使用不同的 ID。priority 200 #節點的權重,主節點需要大于備用節點(數字越大,權重越高,優先級越高)advert_int 1authentication {auth_type PASSauth_pass 123456#同一集群中的所有節點必須使用相同的密碼。}virtual_ipaddress {192.168.48.90 #漂移地址,主備節點一致}track_script {check_mysql} } EOF ?
node02
cat > /etc/keepalived/keepalived.conf << 'EOF' global_defs {vrrp_mcast_group4 224.0.0.18 } ? vrrp_script check_mysql {script "/etc/keepalived/mysql_check.sh" #腳本存放位置internal 2 #執行時間(周期,單位:秒) } ? vrrp_instance DB {state BACKUP#這里主節點為 MASTER,其余的節點(備用節點)修改為 BACKUPinterface ens33 #網卡名稱根據實際情況修改virtual_router_id 51#同一組高可用集群中的所有節點必須設置相同的 ID,不同集群必須使用不> 同的 ID。priority 100 #節點的權重,主節點需要大于備用節點(數字越大,權重越高,優先級越高)advert_int 1authentication {auth_type PASSauth_pass 123456#同一集群中的所有節點必須使用相同的密碼。}virtual_ipaddress {192.168.48.90 #漂移地址,主備節點一致}track_script {check_mysql} } EOF
4. 啟動keepalived
node01&node02
systemctl start keepalived systemctl enable keepalived
5. 驗證故障轉移
查看node01是否存在漂移IP
[root@node01 ~]# ip addr show ens33 | grep 192.168.48.90inet 192.168.48.90/32 scope global ens33
node01關閉mysql,node02查看漂移IP是否到node02。
[root@node01 ~]# systemctl stop mysqld
[root@node02 ~]# ip addr show ens33 | grep 192.168.48.90inet 192.168.48.90/32 scope global ens33
使用其他主機連接數據庫的VIP。連接正常則為成功。
[root@test ~]# mysql -u root -h 192.168.48.90 -P 3306 -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 15 Server version: 8.0.43 MySQL Community Server - GPL
到此,mysql雙機熱備(主主模式)完成。