1. 程式人生 > 程式設計 >記錄一次實踐 MySQL 主從資料庫

記錄一次實踐 MySQL 主從資料庫

前言

之前一直在研究 MySQL 複製問題,所以最近就想動動手將 MySQL 的主從伺服器搭一下。MySQL 主從複製是指資料可以從一個MySQL資料庫伺服器主節點複製到一個或多個從節點。MySQL 預設採用非同步複製方式,這樣從節點不用一直訪問主伺服器來更新自己的資料,資料的更新可以在遠端連線上進行,從節點可以複製主資料庫中的所有資料庫或者特定的資料庫,或者特定的表。

準備工作

  1. MySQL 5.7
  2. Linux
  3. 準備兩臺伺服器兩埠(如果是單機版本準備兩埠)。我這裡是單機版,兩埠是 33063307

實現效果

雙機或單機主從複製,一主一從。

步驟

下文我會稱主伺服器為 Master,從伺服器為 Slave

下載 MySQL 5.7

  1. 通過 下載地址 下載 MySQL 的安裝包
  2. 解壓安裝包 tail zvxf mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz
  3. 複製兩份,命名為 MasterSlave
cp -r 解壓後的MySQL檔案目錄 ./master

cp -r 解壓後的MySQL檔案目錄 ./slave
複製程式碼

建立資料目錄

然後我們建立資料目錄。目前我自己建立的目錄是在 /var/lib/mysql/ 路徑下的,所以我們在此路徑建立兩個名為 MasterSlave 的資料夾。

目前資料夾是為空的,所以我們需要進行初始化資料目錄。所以我們在 Master 和 Slave 的兩個安裝目錄下以下命令

## Master
./bin/mysqld --initialize --user=root --datadir=/var/lib/mysql/master/
複製程式碼

如果成功執行的情況之下,你可以看到一串輸出,裡麵包括一句話,上面說明瞭臨時密碼。這個密碼用於臨時登陸 MySQL,然後再修改密碼的。

2019-11-12T08:43:49.391486Z 1 [Note] A temporary password is generated for root@localhost: %Cx0w5aWACrf
複製程式碼

接下來執行的是 Slave 的資料目錄初始化

## Slave
./bin/mysqld --initialize --user=root --datadir=/var/lib/mysql/slave/
複製程式碼

初始化完畢之後,我們可以走到下一步了

建立配置檔案 my.cnf 並編輯

有人可能不知道 my.cnf 檔案是什麼。其實 my.cnf 就是一個配置檔案,主要配置 MySQL 的服務端,客戶端等配置資訊。

所以我們需要分別為 Master(主) 和 Slave(從) 複製兩份放進各自 MySQL 資料夾,這個是為了區別開各個 MySQL 的配置檔案。然後我們編輯 Mastermy.cnf 檔案,填入以下內容(需要特別注意的是我們應該核對好主從資料庫的資料目錄)

my.cnf

[mysqld]
server-id=1
log-bin=binlog_name
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-do-db=test
log-slave-updates
slave-skip-errors=all
slave-net-timeout=60
user=root
port=3307
datadir=/var/lib/mysql/master
socket=/var/lib/mysql/master/mysql.sock

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

[client]
default-character-set=utf8
port=3306
socket=/var/lib/mysql/master/mysql.sock

[mysql]
default-character-set=utf8
socket=/var/lib/mysql/master/mysql.sock
複製程式碼

然後編輯 Slavemy.cnf

[mysqld]
server-id=2
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
replicate-do-db=test
replicate-ignore-db=mysql
log-slave-updates
slave-skip-errors=all
slave-net-timeout=60
user=root
port=3307
datadir=/var/lib/mysql/slave
socket=/var/lib/mysql/slave/mysql.sock

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

[client]
default-character-set=utf8
port=3306
socket=/var/lib/mysql/slave/mysql.sock

[mysql]
default-character-set=utf8
socket=/var/lib/mysql/slave/mysql.sock
複製程式碼

集中說一下上面配置檔案是什麼意思

  1. server-id 是作為 MySQL 的唯一標識
  2. binlog-ignore-db 是指二進位制日誌會忽略掉資料庫
  3. replicate-do-db 發生改變會被複制的資料庫
  4. replicate-ignore-db 發生改變被忽略的資料庫
  5. socket socket 檔案,用於通訊
  6. port MySQL 埠
  7. datadir 資料目錄地址
  8. log-bin 開啟了二進位制日誌

啟動 MySQL

因為我們是單機版主從資料庫搭建,所以我們需要指定 my.cnf 來啟動 MySQL。下面是啟動的命令列,++我們需要分別在 Master 和 Slave 安裝目錄下執行這句命令++

Master

./bin/mysqld --defaults-file=my.cnf -uroot
複製程式碼

Slave

./bin/mysqld --defaults-file=my.cnf -uroot
複製程式碼

配置 MySQL 的主從資訊

連線 Master 服務端

❤️ 還記得上面的臨時密碼嗎?現在服務端已經啟動好了,現在我們需要拿來登陸服務端。

./bin/mysqld --defaults-file=my.cnf -uroot -p臨時密碼
複製程式碼

登陸成功後,我們首要的事情是修改密碼,因為在臨時登陸情況下服務端不允許進行任何操作。

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password');
複製程式碼

首先我們通過命令列或者客戶端連線上 Master 的 MySQL 伺服器,然後檢視是否開啟了 binlog 二進位制日誌。

show master status;
複製程式碼

如果開啟狀態的話會有以下結果

+--------------------+----------+--------------+--------------------------+-------------------+
| File               | Position | Binlog_Do_DB | Binlog_Ignore_DB         | Executed_Gtid_Set |
+--------------------+----------+--------------+--------------------------+-------------------+
| binlog_name.000005 |      154 |              | information_schema,mysql |                   |
+--------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)
複製程式碼

關於上面的結果我解釋一下

  • File 指的是當前二進位制日誌記錄的檔名
  • Position 指的是二進位制日誌記錄的位置
  • Binlog_Do_DB 是指需要被複制的資料庫
  • Binlog_Ignore_DB 是指被忽略複製的資料庫

現在我們記住 FilePosition,下面在連線 Slave 的時候我們要配置 Master 和 Slave 的資訊對稱問題。

❤️ 然後我們建立一個 test 資料庫,再建立一個 sys_account 表,用於測試主從資訊同步的表。

CREATE TABLE `test`.`sys_account`  (
  `id` int(11) NOT NULL,`username` varchar(255) NULL,PRIMARY KEY (`id`)
);
複製程式碼

❤️ 最後我們需要建立一個賬號,因為主從資料庫的實質++是 Slave 通過特定的賬號登陸 Master 獲取二進位制日誌檔案,然後通過記錄同步到 Slave 資料庫當中++。

// 建立一個使用者名稱為 slave_user,密碼是 slave_pass ,伺服器地址為 slave_host 的賬號,
create user 'slave_user'@'slave_host' identified by 'slave_pass';

// 然後授予所有資料庫的複製許可權給新建的賬號
GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'slave_host';
複製程式碼

至此 Master 的所有操作已經結束了。

連線 Slave 服務端

❤️ 同樣,現在我們需要臨時密碼登陸服務端,然後修改密碼。
❤️ 因為 Slave 只是拿來單純的同步來自於 Master 的資訊,資料庫裡邊是空的,所以我們先要對其和 Master 進行一個資料結構和資料的同步,保證在開始的時候,它們是處於資訊對稱的狀態。我們可以通過 navicat 或者命令列進行同步,這個我就不在這裡展開。

❤️ 現在我們要設定 Slave 資料庫的主伺服器,所以你們需要根據實際情況填寫命令的資訊

CHANGE MASTER TO MASTER_HOST='127.0.0.1',MASTER_USER='slave_user',MASTER_PORT=3306,MASTER_PASSWORD='slave_pass',MASTER_LOG_FILE='binlog_name.000005',MASTER_LOG_POS=154
複製程式碼

引數說明

  • MASTER_HOST 指的是主資料庫的 IP 地址
  • MASTER_USER 指的是剛剛在上面 Master 為 Slave 建立的賬號名
  • MASTER_PORT 指的是主資料庫監聽的埠
  • MASTER_PASSWORD 指的是剛剛在上面 Master 為 Slave 建立的賬號密碼
  • MASTER_LOG_FILE 指的是主伺服器當前二進位制的檔名
  • MASTER_LOG_POS 指的是主伺服器當前二進位制的記錄的位置

常見問題

無法登陸 MySQL

如果新裝的 MySQL 無法登陸,例如提示以下資訊

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
複製程式碼

那麼我們先修改 my.cnf,加上下面這句話

[mysqld]
skip-grant-tables
複製程式碼

然後我們可以直接無賬號密碼登陸 MySQL 服務端,然後我們通過 SQL 命令列修改命令

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password');
複製程式碼

修改完後我們就可以將上面新增的 skip-grant-tables 註釋掉,重新使用新密碼登陸。

遠端登陸問題

有可能你們在遠端伺服器進行搭建的,所以新建的 MySQL 需要開啟遠端連線的選項

# 使所有遠端使用者都可以使用 root 賬號 root 密碼登陸 mysql
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
flush privileges;
複製程式碼

關注我

有興趣的可以關注我,我會持續釋出關於後端、資料庫、訊息佇列中介軟體、高併發等知識!