MySQL主从复制机制及部署

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

什么是MySQL主从复制

MySQL 主从复制通常是用来建立一个和主数据库完全一样的数据库环境,被称为从数据库,MySQL 主从复制默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。
在主从复制的过程中,一个服务器充当一个主数据库,而另外一台服务器充当从服务器,此时主服务器讲本机的操作信息记录至一个特定的二进制文件中。

MySQL主从复制应用场景

  • 数据备份:主从服务器架构的设置,可以大大加强MySQL数据库架构的健壮性。例如:当主服务器出现问题时,我们可以人工或设置自动切换到从服务器继续提供服务,此时从服务器的数据和宕机时的主数据库几乎是一致的。
  • 负载均衡:主从服务器架构可通过程序(PHP、Java等)或代理软件(mysql-proxy、Amoeba)实现对用户(客户端)的请求读写分离,即让从服务器仅仅处理用户的select查询请求,降低用户查询响应时间及读写同时在主服务器上带来的访问压力。对于更新的数据(例如update、insert、delete语句)仍然交给主服务器处理,确保主服务器和从服务器保持实时同步。
  • 横向扩展:将工作负载分发的多个Slave节点上,从而提高系统性能。在这个使用场景下,所有的写(write)和更新(update)操作都在Master节点上完成;所有的读( read)操作都在Slave节点上完成。通过增加更多的Slave节点,便能提高系统的读取速度。

MySQL主从复制架构及原理

MySQl主从复制的前提

1)主服务器一定要打开二进制日志bin-log
2)至少是两台服务器(或者多个实例)
3)主库创建主从复制账号
4)从库必须要有relay-log(中继日志)设置,存放主库返回的二进制日志
5)在复制过程中涉及到的线程
从库会开启一个IO thread(线程),负责连接主库,请求binlog,接收binlog并写入relay-log。
从库会开启一个SQL thread(线程),负责执行relay-log中的事件。
主库会开启一个dump thrad(线程),负责响应从IO thread的请求。

主从复制架构图:

15697380560634.jpg

主从复制原理

1)Master将数据改变记录到二进制日志(binary-log)中,也就是配置文件my.cnf中log-bin指定的文件。

2)在Slave服务器上执行 start slave 命令开启主从复制开关,开始进行主从复制。此时,Slave服务器的IO线程会通过在master上已经授权的复制用户请求连接master服务器,并请求从服务器执行binlog日志文件的指定位置。

3)Master服务器接收到Slave服务器的IO线程请求之后,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。

4)当Slave服务器的IO线程获取到Master服务器上log-dump线程返回的binlog日志内容和日志文件位置后,会将binlog日志内容依次写入到Slave自身的Relay Log (中继日志) 文件 (MySQL-relay-bin.xxx) 的最末端,并将新的binlog文件名和位置记录到master-info中,以便下一次读取master新binlog日志时能告诉master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容。

5)Slave再通过本地SQL线程会实时检测本地Relay Log中IO线程新增的日志内容,然后及时把Relay LOG文件中的内容通过mysqlbinlog工具转换成SQL语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行SQL语句,并在Relay-log.info中记录当前应用中继日志的文件名和位置点,而从达到数据一致

小结:由于主从复制是通过网络来传输bin-log日志来达成一致,一般都会有网了延迟,也可以说是异步。

MySQL binlog日志三种模式

ROW Level

ROW Level记录的方式是行,即如果批量修改数据,记录的不是批量修改的SQL语句事件,而是每条记录被更改的SQL语句,因此,ROW模式的binlog日志文件会变的很“重”


15697409624650.jpg

优点:row level的binlog日志内容会非常清楚的记录下每一行数据被修改的细节。而且不会出现某些特定情况下存储过程或function,以及trigger的调用和触发器无法被正确复制的问题。

缺点:row level下,所有执行的语句当记录到日志中的时候,都以每行记录的修改来记录,这样可能会产生大量的日志内容,产生的binlog日志量是惊人的。批量修改几百万条数据,那么记录几百万行……

Statement Level

记录每一条修改数据的SQL语句(批量修改时,记录的不是单条SQL语句,而是批量修改的SQL语句事件)。看上面的图很好理解row level和statement level两种模式的区别。

优点:statement模式记录的更改的SQ语句事件,并非每条更改记录,所以大大减少了binlog日志量,节约磁盘IO,提高性能。

缺点:statement level下对一些特殊功能的复制效果不是很好,比如:函数、存储过程的复制。由于row level是基于每一行的变化来记录的,所以不会出现类似问题

Mixed

实际上就是前两种模式的结合。在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更

企业场景如何选择binlog的模式
1、 如果生产中使用MySQL的特殊功能相对少(存储过程、触发器、函数)。选择默认的语句模式,Statement Level。
2、 如果生产中使用MySQL的特殊功能较多的,可以选择Mixed模式。
3、 如果生产中使用MySQL的特殊功能较多,又希望数据最大化一致,此时最好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';

主从复制配置搭建

IP地址 配置 系统版本 状态 数据库版本
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二进制安装

下载MySQL8.0二进制版本: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)创建用户组

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)设置基础环境

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)添加启动脚本

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)初始化数据库

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  ]

#连接数据库,输入刚才在日志中的密码
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)数据库加固

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远程登录
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y    #是否删除测试数据库
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y              #是否重新刷新权限表

主从复制配置

Master
添加主从配置及优化参数至my.cnf文件

cat >> /etc/my.cnf << EOF
server-id = 1                                       #一个网络内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                               #跳过域名解析参数
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
添加主从配置及优化参数至my.cnf文件

cat >> /etc/my.cnf << EOF
server-id = 2                                       #一个网络内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                               #跳过域名解析参数
read_only = 1                                       #从库只读 (非root用户)
EOF
/etc/init.d/mysqld restart
Shutting down MySQL...                                     [  OK  ]
Starting MySQL...                                          [  OK  ]

在Master主库上创建用户

#创建专属在备库上能够登录的用户
mysql> create user 'db_repl'@'192.168.31.216' identified with mysql_native_password by '123456';
Query OK, 0 rows affected (0.00 sec)

#授权改用户为slave
mysql> grant replication slave on *.* to 'db_repl'@'192.168.31.216';
Query OK, 0 rows affected (0.00 sec)

#刷新授权
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

#获取主节点当前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备库上设置主节点参数

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)

在备库查看同步状态

15697513927380.jpg

在Slave备库上开启主从同步

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

再次查看同步状态
已经在备库上开启同步,所以IO线程和SQL线程都为YES

15697514793191.jpg

测试主从复制

在Master主库上进行创建,插入操作

#创建测试数据库
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备库上进行查看是否同步

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)

二进制日志管理说明

1)查看二进制日志位置

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)查看二进制日志名称/查看都有哪些二进制日志

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)查看当前使用的binlog二进制日志

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)查看二进制日志格式

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主从复制常见问题

从库binlog落后主库binlog?

从库记录的主库已经传送binlog事件的坐标,一般在繁忙及数据量大的情况下备库会落后于主库。

落后太远的原因:

硬件条件:机器磁盘IO性能不足
网络原因:假如两台设备采用分布式架构,通过公网传输binlog日志。或者内容带宽速率过小
主库存放二进制日志的存储性能太低,建议binlog日志存储在SSD中
主库 dump-log 线程太繁忙,这种情况主要发生在一主多从的架构中
从库IO线程太忙
人为控制(delay节点、延时节点)

主库 update,从库迟迟没有更新

特殊情况:日志已经传过来了,数据并没有同步
一般情况:
1)没有开启SQL线程或者SQL线程故障
2)传的东西有问题(你要做的事情,我提前已经做了,不想重复做了,然后他就死了)
3)SQL线程繁忙
4)人为控制【delay(从库)、延时节点,一般生产设置3-6小时之间,可以保证过去3-6小时之间的误操作,可以避免】

主从复制延时配置(从库配置)

1)停止从库复制

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

2)配置从库延时
修改延时参数master_delay,单位为秒s,配置从库复制主库延迟60s

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

3)启动从库复制

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配置文件,添加只读参数

tail -2 /etc/my.cnf
read_only = 1               #控制普通用户在从库只读
innodb_read_only = 1        #控制root用户在从库只读

添加完成后,重启数据库

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

查看只读状态

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)

主从复制故障及解决(跳过错误)

1)在mysql中配置

#临时停止同步
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

#将同步指针向下移动一个,如果多次不同步,可以重复操作
mysql> set global sql_slave_skip_counter=1;
Query OK, 0 rows affected (0.00 sec)

#启动同步,但是报错如下,是因为我们开启了root只读,在my.cnf中把root只读给关闭掉,然后重启mysql,再进来开启同步
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中可以跳过某些错误,但是最好的解决办法,重新搭建主从复制

延时节点概念

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

原因:
1、主库做操作的对象,在从库不存在
2、主库做操作的对象属性不一致。
3、主库做操作的对象,从库已经存在

备库I/O及SQL线程状态问题

15698092395847.jpg

Slave_IO_Running:I/O线程正在运行状态为 Yes,未运行为 No,正在运行但尚未连接到服务器为 Connecting
Slave_SQL_Running:SQL线程正在运行状态为 Yes,未运行为 No

15698094286554.jpg

主服务器日志坐标:

Master_Log_File 和 Read_Master_Log_Pos 标识主服务器二进制日志中 dump-log 线程已经传输的最近事件的坐标。
如果Master_Log_File和Read_Master_Log_Pos 的值远远落后于主服务器上的那些值,这表示主服务器与从属服务器之间事件的网络传输可能存在延迟

MySQL读写分离

原本我也是想着在主从复制的基础之上把读写分离给做出来,但是考虑再三后觉得没必要,原因如下:

MySQL主从复制本来就不是高可用架构,现在是两台机器跑MySQL主从架构,如果增加了读写分离,就需要多一台机器再做读写分离的代理机,这个时候的架
构就如下图:

15698123581325.jpg

1)此架构中共有三台机器(都是单点),如果任何一台设备故障,则整个程序无法执行查询操作或写入操作。
2)原本是主从是两台设备,在程序中可以写死为读在Slave,写在Master,但是加了一个MySQL Proxy后,程序里连接数据库地址要指向代理机,假如代理机挂掉后,整个集群则无法可用。或者Master节点挂掉后,则无法进行写入操作,Slave节点挂掉后则无法进行读操作
3)简单的主从架构,当Master故障后,一时半会恢复不了业务的情况下,建议将Slave节点从复制集群中择出来跑单机,然后将IP地址换位Master地址即可。

这个时候可能会有同学说,为什么不用MySQL的双主模式,双主模式就可以达到高可用,但是双主模式在数据量大的情况下,很难保证数据的一致性

参考文献

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

你可能感兴趣的:(MySQL主从复制机制及部署)