MySQL主從復(fù)制機(jī)制及部署

原文出自:https://abcops.cn/mysql-replicate/

什么是MySQL主從復(fù)制

MySQL 主從復(fù)制通常是用來建立一個(gè)和主數(shù)據(jù)庫完全一樣的數(shù)據(jù)庫環(huán)境,被稱為從數(shù)據(jù)庫,MySQL 主從復(fù)制默認(rèn)采用異步復(fù)制方式,這樣從節(jié)點(diǎn)不用一直訪問主服務(wù)器來更新自己的數(shù)據(jù),數(shù)據(jù)的更新可以在遠(yuǎn)程連接上進(jìn)行,從節(jié)點(diǎn)可以復(fù)制主數(shù)據(jù)庫中的所有數(shù)據(jù)庫或者特定的數(shù)據(jù)庫,或者特定的表。
在主從復(fù)制的過程中,一個(gè)服務(wù)器充當(dāng)一個(gè)主數(shù)據(jù)庫,而另外一臺(tái)服務(wù)器充當(dāng)從服務(wù)器,此時(shí)主服務(wù)器講本機(jī)的操作信息記錄至一個(gè)特定的二進(jìn)制文件中。

MySQL主從復(fù)制應(yīng)用場景

  • 數(shù)據(jù)備份:主從服務(wù)器架構(gòu)的設(shè)置,可以大大加強(qiáng)MySQL數(shù)據(jù)庫架構(gòu)的健壯性。例如:當(dāng)主服務(wù)器出現(xiàn)問題時(shí),我們可以人工或設(shè)置自動(dòng)切換到從服務(wù)器繼續(xù)提供服務(wù),此時(shí)從服務(wù)器的數(shù)據(jù)和宕機(jī)時(shí)的主數(shù)據(jù)庫幾乎是一致的。
  • 負(fù)載均衡:主從服務(wù)器架構(gòu)可通過程序(PHP、Java等)或代理軟件(mysql-proxy、Amoeba)實(shí)現(xiàn)對用戶(客戶端)的請求讀寫分離,即讓從服務(wù)器僅僅處理用戶的select查詢請求,降低用戶查詢響應(yīng)時(shí)間及讀寫同時(shí)在主服務(wù)器上帶來的訪問壓力。對于更新的數(shù)據(jù)(例如update、insert、delete語句)仍然交給主服務(wù)器處理,確保主服務(wù)器和從服務(wù)器保持實(shí)時(shí)同步。
  • 橫向擴(kuò)展:將工作負(fù)載分發(fā)的多個(gè)Slave節(jié)點(diǎn)上,從而提高系統(tǒng)性能。在這個(gè)使用場景下,所有的寫(write)和更新(update)操作都在Master節(jié)點(diǎn)上完成;所有的讀( read)操作都在Slave節(jié)點(diǎn)上完成。通過增加更多的Slave節(jié)點(diǎn),便能提高系統(tǒng)的讀取速度。

MySQL主從復(fù)制架構(gòu)及原理

MySQl主從復(fù)制的前提

1)主服務(wù)器一定要打開二進(jìn)制日志bin-log
2)至少是兩臺(tái)服務(wù)器(或者多個(gè)實(shí)例)
3)主庫創(chuàng)建主從復(fù)制賬號
4)從庫必須要有relay-log(中繼日志)設(shè)置,存放主庫返回的二進(jìn)制日志
5)在復(fù)制過程中涉及到的線程
從庫會(huì)開啟一個(gè)IO thread(線程),負(fù)責(zé)連接主庫,請求binlog,接收binlog并寫入relay-log。
從庫會(huì)開啟一個(gè)SQL thread(線程),負(fù)責(zé)執(zhí)行relay-log中的事件。
主庫會(huì)開啟一個(gè)dump thrad(線程),負(fù)責(zé)響應(yīng)從IO thread的請求。

主從復(fù)制架構(gòu)圖:

15697380560634.jpg

主從復(fù)制原理

1)Master將數(shù)據(jù)改變記錄到二進(jìn)制日志(binary-log)中,也就是配置文件my.cnf中l(wèi)og-bin指定的文件。

2)在Slave服務(wù)器上執(zhí)行 start slave 命令開啟主從復(fù)制開關(guān),開始進(jìn)行主從復(fù)制。此時(shí),Slave服務(wù)器的IO線程會(huì)通過在master上已經(jīng)授權(quán)的復(fù)制用戶請求連接master服務(wù)器,并請求從服務(wù)器執(zhí)行binlog日志文件的指定位置。

3)Master服務(wù)器接收到Slave服務(wù)器的IO線程請求之后,主節(jié)點(diǎn)會(huì)創(chuàng)建一個(gè)log dump 線程,用于發(fā)送bin-log的內(nèi)容。在讀取bin-log中的操作時(shí),此線程會(huì)對主節(jié)點(diǎn)上的bin-log加鎖,當(dāng)讀取完成,甚至在發(fā)動(dòng)給從節(jié)點(diǎn)之前,鎖會(huì)被釋放。

4)當(dāng)Slave服務(wù)器的IO線程獲取到Master服務(wù)器上log-dump線程返回的binlog日志內(nèi)容和日志文件位置后,會(huì)將binlog日志內(nèi)容依次寫入到Slave自身的Relay Log (中繼日志) 文件 (MySQL-relay-bin.xxx) 的最末端,并將新的binlog文件名和位置記錄到master-info中,以便下一次讀取master新binlog日志時(shí)能告訴master服務(wù)器從新binlog日志的指定文件及位置開始讀取新的binlog日志內(nèi)容。

5)Slave再通過本地SQL線程會(huì)實(shí)時(shí)檢測本地Relay Log中IO線程新增的日志內(nèi)容,然后及時(shí)把Relay LOG文件中的內(nèi)容通過mysqlbinlog工具轉(zhuǎn)換成SQL語句,并在自身Slave服務(wù)器上按解析SQL語句的位置順序執(zhí)行SQL語句,并在Relay-log.info中記錄當(dāng)前應(yīng)用中繼日志的文件名和位置點(diǎn),而從達(dá)到數(shù)據(jù)一致

小結(jié):由于主從復(fù)制是通過網(wǎng)絡(luò)來傳輸bin-log日志來達(dá)成一致,一般都會(huì)有網(wǎng)了延遲,也可以說是異步。

MySQL binlog日志三種模式

ROW Level

ROW Level記錄的方式是行,即如果批量修改數(shù)據(jù),記錄的不是批量修改的SQL語句事件,而是每條記錄被更改的SQL語句,因此,ROW模式的binlog日志文件會(huì)變的很“重”


15697409624650.jpg

優(yōu)點(diǎn):row level的binlog日志內(nèi)容會(huì)非常清楚的記錄下每一行數(shù)據(jù)被修改的細(xì)節(jié)。而且不會(huì)出現(xiàn)某些特定情況下存儲(chǔ)過程或function,以及trigger的調(diào)用和觸發(fā)器無法被正確復(fù)制的問題。

缺點(diǎn):row level下,所有執(zhí)行的語句當(dāng)記錄到日志中的時(shí)候,都以每行記錄的修改來記錄,這樣可能會(huì)產(chǎn)生大量的日志內(nèi)容,產(chǎn)生的binlog日志量是驚人的。批量修改幾百萬條數(shù)據(jù),那么記錄幾百萬行……

Statement Level

記錄每一條修改數(shù)據(jù)的SQL語句(批量修改時(shí),記錄的不是單條SQL語句,而是批量修改的SQL語句事件)。看上面的圖很好理解row level和statement level兩種模式的區(qū)別。

優(yōu)點(diǎn):statement模式記錄的更改的SQ語句事件,并非每條更改記錄,所以大大減少了binlog日志量,節(jié)約磁盤IO,提高性能。

缺點(diǎn):statement level下對一些特殊功能的復(fù)制效果不是很好,比如:函數(shù)、存儲(chǔ)過程的復(fù)制。由于row level是基于每一行的變化來記錄的,所以不會(huì)出現(xiàn)類似問題

Mixed

實(shí)際上就是前兩種模式的結(jié)合。在Mixed模式下,MySQL會(huì)根據(jù)執(zhí)行的每一條具體的sql語句來區(qū)分對待記錄的日志形式,也就是在Statement和Row之間選擇一種。如果sql語句確實(shí)就是update或者delete等修改數(shù)據(jù)的語句,那么還是會(huì)記錄所有行的變更

企業(yè)場景如何選擇binlog的模式
1、 如果生產(chǎn)中使用MySQL的特殊功能相對少(存儲(chǔ)過程、觸發(fā)器、函數(shù))。選擇默認(rèn)的語句模式,Statement Level。
2、 如果生產(chǎn)中使用MySQL的特殊功能較多的,可以選擇Mixed模式。
3、 如果生產(chǎn)中使用MySQL的特殊功能較多,又希望數(shù)據(jù)最大化一致,此時(shí)最好Row level模式;但是要注意,該模式的binlog非?!俺林亍?。

查看binlog模式

mysql> show global variables like "%binlog_format%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

配置binlog模式

cat /etc/my.cnf | grep binlog
log-bin = /usr/local/mysql/binlogs/mysql-bin
max_binlog_size = 100M
binlog_expire_logs_seconds = 604800
binlog_cache_size=1048576
binlog_format='ROW'                 #行模式
#binlog_format='STATEMENT'          #SQL語句模式
#binlog_format='MIXED'              #混合模式
binlog_stmt_cache_size=1048576
sync_binlog=100

不重啟,使配置在msyql中生效

SET global binlog_format='STATEMENT';

主從復(fù)制配置搭建

IP地址 配置 系統(tǒng)版本 狀態(tài) 數(shù)據(jù)庫版本
192.168.31.215 2c/4G CentOS 7.6.1810 Master mysql-8.0.17
192.168.31.216 2c/4G CentOS 7.6.1810 Slave mysql-8.0.17

MySQL8二進(jìn)制安裝

下載MySQL8.0二進(jìn)制版本:wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.17-linux-glibc2.12-x86_64.tar.xz

1) 安裝依賴

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all && yum makecache
yum install libaio.x86_64 libaio-devel.x86_64 -y

2)創(chuàng)建用戶組

groupadd mysql
useradd -r -g mysql -s /bin/false mysql
tar xf mysql-8.0.17-linux-glibc2.12-x86_64.tar.xz -C /usr/local/
cd /usr/local/
mv mysql-8.0.17-linux-glibc2.12-x86_64 mysql

3)設(shè)置基礎(chǔ)環(huán)境

mkdir mysql/mysql-files
chown mysql.mysql mysql/mysql-files/
echo 'export PATH=$PATH:/usr/local/mysql/bin' > /etc/profile.d/mysql.sh
source /etc/profile
mkdir -p /usr/local/mysql/{data,run,log} 
chown -Rf mysql.mysql /usr/local/mysql/{data,run,log}

4)添加啟動(dòng)腳本

cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld 
chkconfig --add mysqld

5)my.cnf配置

cat /etc/my.cnf
[client]
port = 3306
socket = /usr/local/mysql/run/mysql.sock

[mysqld]
local_infile = 1 
secure_file_priv = /tmp
log_timestamps=SYSTEM
default-time_zone = '+8:00'
port = 3306
wait_timeout = 28800
socket = /usr/local/mysql/run/mysql.sock
pid_file = /usr/local/mysql/run/mysql.pid
datadir = /usr/local/mysql/data
basedir = /usr/local/mysql
default_storage_engine = InnoDB
default_authentication_plugin=mysql_native_password
max_allowed_packet = 512M
max_connections = 65536
open_files_limit = 65536
log_bin_trust_function_creators=1
skip-name-resolve
lower_case_table_names=1
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
innodb_read_io_threads = 16
innodb_io_capacity = 2000
innodb_buffer_pool_size = 8192M
innodb_log_file_size = 128M
innodb_file_per_table = 1 
innodb_flush_log_at_trx_commit = 0 
key_buffer_size = 512M
log-error = /usr/local/mysql/log/mysql_error.log

6)初始化數(shù)據(jù)庫

bin/mysqld --initialize --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/log/mysql_error.log --open-files-limit=65536 --pid-file=/usr/local/mysql/run/mysql.pid --socket=/usr/local/mysql/run/mysql.sock --port=3306 

查看密碼:

cat log/mysql_error.log | grep password
2019-09-29T16:27:15.074787+08:00 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: uqpIwWffn7=E       #記住此密碼

7)加密連接

bin/mysql_ssl_rsa_setup 

Generating a 2048 bit RSA private key
...........................................................+++
..........................................................+++
writing new private key to 'ca-key.pem'
-----
Generating a 2048 bit RSA private key
...........................................+++
................................................................+++
writing new private key to 'server-key.pem'
-----
Generating a 2048 bit RSA private key
............................................+++
.........................................+++
writing new private key to 'client-key.pem'
-----

8)修改root密碼

/etc/init.d/mysqld restart 
Shutting down MySQL..                                      [  OK  ]
Starting MySQL...                                          [  OK  ]

#連接數(shù)據(jù)庫,輸入剛才在日志中的密碼
mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.17

#修改root密碼采用mysql_native_password加密方式
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password by '123456';
Query OK, 0 rows affected (0.01 sec)

#修改root密碼采用caching_sha2_password加密方式(與上面的二選一即可)
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password by '123456';
Query OK, 0 rows affected (0.01 sec)

mysql> use mysql;
Database changed

#查看密碼所采用的加密方式,在plugin列
mysql> select host, user, authentication_string, plugin from user;
+-----------+------------------+------------------------------------------------------------------------+-----------------------+
| host      | user             | authentication_string                                                  | plugin                |
+-----------+------------------+------------------------------------------------------------------------+-----------------------+
| localhost | mysql.infoschema | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | caching_sha2_password |
| localhost | mysql.session    | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | caching_sha2_password |
| localhost | mysql.sys        | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | caching_sha2_password |
| localhost | root             | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9                              | mysql_native_password |
+-----------+------------------+------------------------------------------------------------------------+-----------------------+
4 rows in set (0.00 sec)

9)數(shù)據(jù)庫加固

mysql_secure_installation
Enter password for user root:       #輸入root密碼
Change the password for root ? ((Press y|Y for Yes, any other key for No) : No          #是否修改root密碼
Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y                   #是否刪除匿名用戶
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y             #是否允許root遠(yuǎn)程登錄
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y    #是否刪除測試數(shù)據(jù)庫
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y              #是否重新刷新權(quán)限表

主從復(fù)制配置

Master
添加主從配置及優(yōu)化參數(shù)至my.cnf文件

cat >> /etc/my.cnf << EOF
server-id = 1                                       #一個(gè)網(wǎng)絡(luò)內(nèi)server-id不能相同
log-bin = /usr/local/mysql/binlogs/mysql-bin        #binlog日志位置
max_binlog_size = 100M
binlog_expire_logs_seconds = 604800
binlog_cache_size=1048576
binlog_format='STATEMENT'
binlog_stmt_cache_size=1048576
log_queries_not_using_indexes=ON
sync_binlog=100
innodb_flush_log_at_trx_commit=2
skip_name_resolve = 0                               #跳過域名解析參數(shù)
EOF
mkdir -p /usr/local/mysql/binlogs
chown -Rf mysql.mysql binlogs/

/etc/init.d/mysqld restart
Shutting down MySQL..                                      [  OK  ]
Starting MySQL...                                          [  OK  ]

Slave
添加主從配置及優(yōu)化參數(shù)至my.cnf文件

cat >> /etc/my.cnf << EOF
server-id = 2                                       #一個(gè)網(wǎng)絡(luò)內(nèi)server-id不能相同
max_binlog_size = 100M
binlog_expire_logs_seconds = 604800
binlog_cache_size=1048576
binlog_format='STATEMENT'
binlog_stmt_cache_size=1048576
log_queries_not_using_indexes=ON
sync_binlog=100
innodb_flush_log_at_trx_commit=2
skip_name_resolve = 0                               #跳過域名解析參數(shù)
read_only = 1                                       #從庫只讀 (非root用戶)
EOF
/etc/init.d/mysqld restart
Shutting down MySQL...                                     [  OK  ]
Starting MySQL...                                          [  OK  ]

在Master主庫上創(chuàng)建用戶

#創(chuàng)建專屬在備庫上能夠登錄的用戶
mysql> create user 'db_repl'@'192.168.31.216' identified with mysql_native_password by '123456';
Query OK, 0 rows affected (0.00 sec)

#授權(quán)改用戶為slave
mysql> grant replication slave on *.* to 'db_repl'@'192.168.31.216';
Query OK, 0 rows affected (0.00 sec)

#刷新授權(quán)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

#獲取主節(jié)點(diǎn)當(dāng)前binary log文件名稱及位置
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 |      155 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

在Slave備庫上設(shè)置主節(jié)點(diǎn)參數(shù)

mysql> change master to
master_host='192.168.31.215',
master_user='db_repl',
master_password='123456',
master_log_file='mysql-bin.000002',
master_log_pos=155;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

在備庫查看同步狀態(tài)

15697513927380.jpg

在Slave備庫上開啟主從同步

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

再次查看同步狀態(tài)
已經(jīng)在備庫上開啟同步,所以IO線程和SQL線程都為YES

15697514793191.jpg

測試主從復(fù)制

在Master主庫上進(jìn)行創(chuàng)建,插入操作

#創(chuàng)建測試數(shù)據(jù)庫
mysql> create database db_mysql;
Query OK, 1 row affected (0.00 sec)

mysql> use db_mysql;
Database changed
mysql> CREATE TABLE `event_log` (
    `dbname` varchar(128) NOT NULL DEFAULT '',
    `eventname` varchar(128) NOT NULL DEFAULT '',
    `starttime` datetime NOT NULL DEFAULT '1979-01-01 00:00:00',
    `endtime` datetime DEFAULT NULL,
    `issuccess` int(11) DEFAULT NULL,
    `duration` int(11) DEFAULT NULL,
    `errormessage` varchar(512) DEFAULT NULL,
    `randno` int(11) DEFAULT NULL,
    PRIMARY KEY (`dbname`,`eventname`,`starttime`),
    KEY `idx_event_log_endtime` (`endtime`),
    KEY `idx_event_log_starttime_randno` (`starttime`,`randno`),
    KEY `idx_eventlog_stt_scs` (`starttime`,`issuccess`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected, 4 warnings (0.04 sec)

mysql> show tables;
+--------------------+
| Tables_in_db_mysql |
+--------------------+
| event_log          |
+--------------------+
1 row in set (0.00 sec)

在Slave備庫上進(jìn)行查看是否同步

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| db_mysql           |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

mysql> use db_mysql;
Database changed

mysql> show tables;
+--------------------+
| Tables_in_db_mysql |
+--------------------+
| event_log          |
+--------------------+
1 row in set (0.01 sec)

二進(jìn)制日志管理說明

1)查看二進(jìn)制日志位置

mysql> show variables like '%log_bin%';
+---------------------------------+------------------------------------------+
| Variable_name                   | Value                                    |
+---------------------------------+------------------------------------------+
| log_bin                         | ON                                       |
| log_bin_basename                | /usr/local/mysql/binlogs/mysql-bin       |
| log_bin_index                   | /usr/local/mysql/binlogs/mysql-bin.index |
| log_bin_trust_function_creators | ON                                       |
| log_bin_use_v1_row_events       | OFF                                      |
| sql_log_bin                     | ON                                       |
+---------------------------------+------------------------------------------+
6 rows in set (0.01 sec)

2)查看二進(jìn)制日志名稱/查看都有哪些二進(jìn)制日志

mysql> show binary logs;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 |       178 | No        |
| mysql-bin.000002 |      1140 | No        |
+------------------+-----------+-----------+
2 rows in set (0.00 sec)

3)查看當(dāng)前使用的binlog二進(jìn)制日志

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 |     1140 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

4)查看二進(jìn)制日志格式

mysql> show variables like '%format%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| binlog_format                   | STATEMENT |
| default_week_format             | 0         |
| information_schema_stats_expiry | 86400     |
| innodb_default_row_format       | dynamic   |
+---------------------------------+-----------+
4 rows in set (0.00 sec)

MySQL主從復(fù)制常見問題

從庫binlog落后主庫binlog?

從庫記錄的主庫已經(jīng)傳送binlog事件的坐標(biāo),一般在繁忙及數(shù)據(jù)量大的情況下備庫會(huì)落后于主庫。

落后太遠(yuǎn)的原因:

硬件條件:機(jī)器磁盤IO性能不足
網(wǎng)絡(luò)原因:假如兩臺(tái)設(shè)備采用分布式架構(gòu),通過公網(wǎng)傳輸binlog日志。或者內(nèi)容帶寬速率過小
主庫存放二進(jìn)制日志的存儲(chǔ)性能太低,建議binlog日志存儲(chǔ)在SSD中
主庫 dump-log 線程太繁忙,這種情況主要發(fā)生在一主多從的架構(gòu)中
從庫IO線程太忙
人為控制(delay節(jié)點(diǎn)、延時(shí)節(jié)點(diǎn))

主庫 update,從庫遲遲沒有更新

特殊情況:日志已經(jīng)傳過來了,數(shù)據(jù)并沒有同步
一般情況:
1)沒有開啟SQL線程或者SQL線程故障
2)傳的東西有問題(你要做的事情,我提前已經(jīng)做了,不想重復(fù)做了,然后他就死了)
3)SQL線程繁忙
4)人為控制【delay(從庫)、延時(shí)節(jié)點(diǎn),一般生產(chǎn)設(shè)置3-6小時(shí)之間,可以保證過去3-6小時(shí)之間的誤操作,可以避免】

主從復(fù)制延時(shí)配置(從庫配置)

1)停止從庫復(fù)制

mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

2)配置從庫延時(shí)
修改延時(shí)參數(shù)master_delay,單位為秒s,配置從庫復(fù)制主庫延遲60s

mysql> change master to master_delay = 60;
Query OK, 0 rows affected (0.01 sec)

3)啟動(dòng)從庫復(fù)制

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

4)查看配置是否生效

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.31.215
                  Master_User: db_repl
                  Master_Port: 3306
                Connect_Retry: 60           #連接延遲60秒

從庫安全配置(其他用戶只讀)

修改my.cnf配置文件,添加只讀參數(shù)

tail -2 /etc/my.cnf
read_only = 1               #控制普通用戶在從庫只讀
innodb_read_only = 1        #控制root用戶在從庫只讀

添加完成后,重啟數(shù)據(jù)庫

service mysqld restart
Shutting down MySQL...                                     [  OK  ]
Starting MySQL...                                          [  OK  ]

查看只讀狀態(tài)

mysql> show variables like '%read_only%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | ON    |           #root用戶只讀
| read_only             | ON    |           #普通用戶只讀
| super_read_only       | OFF   |
| transaction_read_only | OFF   |
+-----------------------+-------+
4 rows in set (0.01 sec)

主從復(fù)制故障及解決(跳過錯(cuò)誤)

1)在mysql中配置

#臨時(shí)停止同步
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

#將同步指針向下移動(dòng)一個(gè),如果多次不同步,可以重復(fù)操作
mysql> set global sql_slave_skip_counter=1;
Query OK, 0 rows affected (0.00 sec)

#啟動(dòng)同步,但是報(bào)錯(cuò)如下,是因?yàn)槲覀冮_啟了root只讀,在my.cnf中把root只讀給關(guān)閉掉,然后重啟mysql,再進(jìn)來開啟同步
mysql> start slave;
ERROR 1036 (HY000): Table 'slave_master_info' is read only
tail -2 /etc/my.cnf
read_only = 1
#innodb_read_only = 1       #注釋掉root只讀

/etc/init.d/mysqld restart  #重啟mysqld
Shutting down MySQL..                                      [  OK  ]
Starting MySQL...                                          [  OK  ]
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

在mysql中可以跳過某些錯(cuò)誤,但是最好的解決辦法,重新搭建主從復(fù)制

延時(shí)節(jié)點(diǎn)概念

此操作通過 show slave status\G; 命令看到
Last_SQL_Errno: 0
Last_SQL_Error: 

原因:
1、主庫做操作的對象,在從庫不存在
2、主庫做操作的對象屬性不一致。
3、主庫做操作的對象,從庫已經(jīng)存在

備庫I/O及SQL線程狀態(tài)問題

15698092395847.jpg

Slave_IO_Running:I/O線程正在運(yùn)行狀態(tài)為 Yes,未運(yùn)行為 No,正在運(yùn)行但尚未連接到服務(wù)器為 Connecting
Slave_SQL_Running:SQL線程正在運(yùn)行狀態(tài)為 Yes,未運(yùn)行為 No

15698094286554.jpg

主服務(wù)器日志坐標(biāo):

Master_Log_File 和 Read_Master_Log_Pos 標(biāo)識主服務(wù)器二進(jìn)制日志中 dump-log 線程已經(jīng)傳輸?shù)淖罱录淖鴺?biāo)。
如果Master_Log_File和Read_Master_Log_Pos 的值遠(yuǎn)遠(yuǎn)落后于主服務(wù)器上的那些值,這表示主服務(wù)器與從屬服務(wù)器之間事件的網(wǎng)絡(luò)傳輸可能存在延遲

MySQL讀寫分離

原本我也是想著在主從復(fù)制的基礎(chǔ)之上把讀寫分離給做出來,但是考慮再三后覺得沒必要,原因如下:

MySQL主從復(fù)制本來就不是高可用架構(gòu),現(xiàn)在是兩臺(tái)機(jī)器跑MySQL主從架構(gòu),如果增加了讀寫分離,就需要多一臺(tái)機(jī)器再做讀寫分離的代理機(jī),這個(gè)時(shí)候的架
構(gòu)就如下圖:

15698123581325.jpg

1)此架構(gòu)中共有三臺(tái)機(jī)器(都是單點(diǎn)),如果任何一臺(tái)設(shè)備故障,則整個(gè)程序無法執(zhí)行查詢操作或?qū)懭氩僮鳌?br> 2)原本是主從是兩臺(tái)設(shè)備,在程序中可以寫死為讀在Slave,寫在Master,但是加了一個(gè)MySQL Proxy后,程序里連接數(shù)據(jù)庫地址要指向代理機(jī),假如代理機(jī)掛掉后,整個(gè)集群則無法可用。或者M(jìn)aster節(jié)點(diǎn)掛掉后,則無法進(jìn)行寫入操作,Slave節(jié)點(diǎn)掛掉后則無法進(jìn)行讀操作
3)簡單的主從架構(gòu),當(dāng)Master故障后,一時(shí)半會(huì)恢復(fù)不了業(yè)務(wù)的情況下,建議將Slave節(jié)點(diǎn)從復(fù)制集群中擇出來跑單機(jī),然后將IP地址換位Master地址即可。

這個(gè)時(shí)候可能會(huì)有同學(xué)說,為什么不用MySQL的雙主模式,雙主模式就可以達(dá)到高可用,但是雙主模式在數(shù)據(jù)量大的情況下,很難保證數(shù)據(jù)的一致性

參考文獻(xiàn)

感謝各位:
www.cnblogs.com/clsn/p/8087678.html
https://blog.csdn.net/zyhlwzy/article/details/80569422
https://blog.51cto.com/zhangxinqi/2178407

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容