以前一直在研究 MySQL 複製問題,因此最近就想動動手將 MySQL 的主從服務器搭一下。MySQL 主從複製是指數據能夠從一個MySQL數據庫服務器主節點複製到一個或多個從節點。MySQL 默認採用異步複製方式,這樣從節點不用一直訪問主服務器來更新本身的數據,數據的更新能夠在遠程鏈接上進行,從節點能夠複製主數據庫中的全部數據庫或者特定的數據庫,或者特定的表。mysql
MySQL 5.7
Linux
3306
、3307
雙機或單機主從複製,一主一從。linux
下文我會稱主服務器爲 Master
,從服務器爲 Slave
。sql
tail zvxf mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz
Master
和 Slave
cp -r 解壓後的MySQL文件目錄 ./master
cp -r 解壓後的MySQL文件目錄 ./slave
複製代碼
而後咱們建立數據目錄。目前我本身建立的目錄是在 /var/lib/mysql/
路徑下的,因此咱們在此路徑建立兩個名爲 Master
和 Slave
的文件夾。數據庫
目前文件夾是爲空的,因此咱們須要進行初始化數據目錄。因此咱們在 Master 和 Slave 的兩個安裝目錄下如下命令後端
## Master
./bin/mysqld --initialize --user=root --datadir=/var/lib/mysql/master/
複製代碼
若是成功執行的狀況之下,你能夠看到一串輸出,裏面包括一句話,上面說明了臨時密碼。這個密碼用於臨時登錄 MySQL,而後再修改密碼的。bash
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
就是一個配置文件,主要配置 MySQL
的服務端,客戶端等配置信息。併發
因此咱們須要分別爲 Master(主) 和 Slave(從) 複製兩份放進各自 MySQL
文件夾,這個是爲了區別開各個 MySQL
的配置文件。而後咱們編輯 Master
的 my.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
複製代碼
而後編輯 Slave
的 my.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
複製代碼
集中說一下上面配置文件是什麼意思
server-id
是做爲 MySQL 的惟一標識binlog-ignore-db
是指二進制日誌會忽略掉數據庫replicate-do-db
發生改變會被複制的數據庫replicate-ignore-db
發生改變被忽略的數據庫socket
socket 文件,用於通訊port
MySQL 端口datadir
數據目錄地址log-bin
開啓了二進制日誌由於咱們是單機版主從數據庫搭建,因此咱們須要指定 my.cnf 來啓動 MySQL。下面是啓動的命令行,++咱們須要分別在 Master 和 Slave 安裝目錄下執行這句命令++
Master
./bin/mysqld --defaults-file=my.cnf -uroot
複製代碼
Slave
./bin/mysqld --defaults-file=my.cnf -uroot
複製代碼
❤️ 還記得上面的臨時密碼嗎?如今服務端已經啓動好了,如今咱們須要拿來登錄服務端。
./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
是指被忽略複製的數據庫如今咱們記住 File
和 Position
,下面在鏈接 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 只是拿來單純的同步來自於 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 沒法登錄,例如提示如下信息
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;
複製代碼
有興趣的能夠關注我,我會持續發佈關於後端、數據庫、消息隊列中間件、高併發等知識!