mysql-主从复制

Posted 小芃总

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql-主从复制相关的知识,希望对你有一定的参考价值。

1.主从简介

mysql 的主从复制(Replication)至少需要两个MySQL服务(可以是同一台机器,也可以是不同机器之间进行)。

MySQL 数据库的主从复制方案,与使用scp/rsync等命令进行的文件级别复制类似,都是数据的远程传输。只不过MySQL的主从复制是其自带的功能,无需借助第三方工具,而且MySQL的主从复制并不是数据库磁盘上的文件直接拷贝,而是通过逻辑的binlog日志复制到要同步的服务器本地,然后由本地的线程读取日志里面的SQL语句,重新应用到MySQL 数据库中。

1.1 作用

  1. 可以实时灾备,用于故障切换;
  2. 读写分离,提供查询服务,实现负载均衡;
  3. 数据热备,避免影响业务。

1.2 形式

  • 一主一从
  • 主主复制
  • 一主多从---扩展系统读取的性能,因为读是在从库读取的
  • 多主一从---5.7开始支持
  • 联级复制

2.主从复制原理

技术图片

1.主数据库服务将所有写操作记录在binlog日志中,并产生log dump线程(接受到从数据库服务的I/O线程请求后将binlog日志发送给IO线程)

2.从服务器MySQL服务生成两个线程,一个是 I/O 线程,另一个是 SQL 线程。

3.从库 I/O 线程去请求主库的binlog日志,并将binlog日志中的文件写入relaylog(中继日志)中

4.从库的 SQL 线程会读取relaylog中的内容,并解析成具体的操作,来实现主从的操作一致,达到最终两个数据库数据一致的目的,这个过程为重放

3.主从配置

开启主从复制时,需使主从数据库数据一致(即全备后在从数据库恢复),否则在主操从库没有的数据时,从库复制功能会受到影响,直到重新设置从库记录主库的日志位置

参数

  • 主库参数
参数 作用
binlog 开启二进制日志记录
server-id 数据库服务唯一标识,主库id小于从库
innodb_flush_log_at_trx_commit 0,表示提交事务后,重做日志不会写入日志文件
1,同步写入日志文件
2,异步写入日志文件
innodb_support_xa=1 确保二进制日志和innodb数据文件的同步
保证复制环境的数据一致
log_bin_index 二进制日志索引名称
binlog_format 二进制日志的类型
binlog_row_image 二进制镜像保存量
binlog_do_db,binlog_ignore_db 记录在二进制日志中和不记录在二进制日志中
replicate_do_db[table] slave只重放指定的库/表
replicate_ignore_db[table] slave忽略重放指定的库/表
replicate_wild_do_table slave重放满足匹配的表
replicate_wild_ignore_table slave忽略重放满足匹配条件的表
binlog_cache_size 缓存还没刷新到磁盘的binlog日志
max_binlog_size 二进制日志最大值
expire_logs_days 二进制日志被保留的有效期
sync_binlog 二进制日志刷新到磁盘频率
binlog_rows_query_log_events 二进制日志基于行,用来指定额外的信息
  • 从库参数
参数 作用
relay_log 从节点中继日志名
relay_log_index 中继日志索引名称
replicate_do_db和replicate_ignore_db 过滤那些会被应用到从节点
slave_skip_errors 自动忽略指定错误,逗号分割
slave_exec_mode 取值IDEMPOTENT,STRICE 是否自动忽略重复主键和主键找不到错误
log_slave_updates 启动从节点的二进制日志
relay_log_purge 如何清除中继日志文件,默认1 自动清理
read_only 从库只读,SUPER权限用户除外
super_read_only SUPER用户设置只读
skip_slave_start 从节点跳过自动开启复制
sync_relay_log和sysnc_relay_log_info 中继日志文件同步频率,默认10000
repost_host 区别不同的从节点,SHOW SLAVE HOSTS查看
slave_max_allowed_packet 从节点的SQL和IO线程允许最大的数据包容量
relay_log_recovery 中继日志自动恢复,从库意外停止后使用
master_info_repository slave master节点信息保留在位置,默认file
relay_log_info_repository 从节点信息slave保留在位置,默认file

3.1主数据库

  • vm1(192.168.225.129)
  • 主库当前数据
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wisan_db           |
+--------------------+
5 rows in set (0.01 sec)

mysql> show tables from wisan_db;
+--------------------+
| Tables_in_wisan_db |
+--------------------+
| student_info       |
+--------------------+
1 row in set (0.00 sec)

mysql> select * from wisan_db.student_info;
+----+-------+------+
| id | name  | age  |
+----+-------+------+
|  1 | wisan |   18 |
|  2 | fyj   |   17 |
|  3 | flora |   19 |
|  4 | wang  |   20 |
+----+-------+------+
4 rows in set (0.04 sec)

创建同步账号并授权给从数据库使用

##replication slave 为权限类型
##授权的同时创建用户
mysql> grant replication slave on *.* to ‘repli‘@‘192.168.225.130‘ identified by ‘123456‘;
Query OK, 0 rows affected, 1 warning (0.00 sec)

##查看repli用户的slave权限
mysql> select user,repl_slave_priv from mysql.user where user=‘repli‘;
+-------+-----------------+
| user  | repl_slave_priv |
+-------+-----------------+
| repli | Y               |
+-------+-----------------+

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

配置主数据库

[root@vm1 ~]# vim /etc/my.cnf 
[mysqld]
basedir=/usr/local/mysql
datadir=/opt/mysql_data/data
socket=/tmp/mysql.sock
port=3306
pid-file=/opt/mysql_data/data/mysql.pid
user=mysql
skip-name-resolve
symbolic-links=0

server-id=10           ##数据库服务器标识,要求主库的id小于从库
log-bin=mysql-bin      ##开启binlog日志

重启服务

[root@vm1 ~]# service mysqld restart 
Shutting down MySQL.. SUCCESS! 
Starting MySQL.. SUCCESS! 
[root@vm1 ~]# ss -antl 
State          Recv-Q          Send-Q                   Local Address:Port                   Peer Address:Port         
LISTEN         0               128                            0.0.0.0:22                          0.0.0.0:*            
LISTEN         0               128                               [::]:22                             [::]:*            
LISTEN         0               80                                   *:3306                              *:*            
[root@vm1 ~]# ls /opt/mysql_data/data/
auto.cnf        ibdata1      ib_logfile1  mysql             mysql-bin.index  performance_schema  vm1.localdomain.err
ib_buffer_pool  ib_logfile0  ibtmp1       mysql-bin.000001  mysql.pid        sys                 wisan_db
[root@vm1 ~]# 

查看主库状态

  • 查看此时主库binlog记录的位置
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

3.2从数据库

  • vm3(192.168.225.130)

配置文件

[root@vm3 ~]# vim /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/opt/mysql_data/data
socket=/tmp/mysql.sock
port=3306
pid-file=/opt/mysql_data/data/mysql.pid
user=mysql
skip-name-resolve
symbolic-links=0

server-id=20                 ##数据库服务器标识,从库id大于主库
relay-log=mysql-relay-bin    ##启用中继日志

重启数据库服务

[root@vm3 ~]# service mysqld restart 
Shutting down MySQL.. SUCCESS! 
Starting MySQL.. SUCCESS! 
[root@vm3 ~]# ss -antl
State      Recv-Q     Send-Q         Local Address:Port          Peer Address:Port     
LISTEN     0          128                  0.0.0.0:22                 0.0.0.0:*        
LISTEN     0          80                         *:3306                     *:*        
LISTEN     0          128                     [::]:22                    [::]:*        
[root@vm3 ~]# ls /opt/mysql_data/data/
auto.cnf        ib_logfile0  mysql               sys
ib_buffer_pool  ib_logfile1  mysql.pid           vm3.localdomain.err
ibdata1         ibtmp1       performance_schema

配置并启动主从复制

mysql> change master to
    -> master_host=‘192.168.225.129‘,
    -> master_user=‘repli‘,
    -> master_password=‘123456‘,
    -> master_log_file=‘mysql-bin.000001‘,
    -> master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

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

查看从库状态

mysql> show slave status G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.225.129
                  Master_User: repli
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes          ##yes表示从库io启动成功
            Slave_SQL_Running: Yes          ##yes表示从库重放功能运行成功
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
......................................................

3.3主从复制测试

查看从库当前数据

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

主库更新数据

## 创建新数据库
mysql> create database country;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| country            |
| mysql              |
| performance_schema |
| sys                |
| wisan_db           |
+--------------------+

##创建新表
mysql> use country;
Database changed
mysql> create table id_name(
    -> id int not null primary key auto_increment,
    -> name varchar(100) not null
    -> );

mysql> desc country.id_name;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(100) | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> insert into id_name(name) values(‘CHINA‘),(‘The United States‘),(‘The United Kingdom‘),(‘Japan‘);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from country.id_name;
+----+--------------------+
| id | name               |
+----+--------------------+
|  1 | CHINA              |
|  2 | The United States  |
|  3 | The United Kingdom |
|  4 | Japan              |
+----+--------------------+

查看从库是否更新

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

mysql> show tables from country;
+-------------------+
| Tables_in_country |
+-------------------+
| id_name           |
+-------------------+
1 row in set (0.01 sec)

mysql> select * from country.id_name;
+----+--------------------+
| id | name               |
+----+--------------------+
|  1 | CHINA              |
|  2 | The United States  |
|  3 | The United Kingdom |
|  4 | Japan              |
+----+--------------------+
4 rows in set (0.00 sec)

在主库更新从库没有的数据

mysql> show tables from wisan_db;
+--------------------+
| Tables_in_wisan_db |
+--------------------+
| student_info       |
| student_score      |
+--------------------+
2 rows in set (0.00 sec)

mysql> insert into wisan_db.student_info(name,age) value(‘hello‘,null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from wisan_db.student_info;
+----+-------+------+
| id | name  | age  |
+----+-------+------+
|  1 | wisan |   18 |
|  2 | fyj   |   17 |
|  3 | flora |   19 |
|  4 | wang  |   20 |
|  5 | hello | NULL |
+----+-------+------+
5 rows in set (0.00 sec)

查看从库数据

  • 发现从库在复制时发生错误
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| country            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
##查看状态
mysql> show slave status G;
   Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1146
                   Last_Error: Error executing row event: ‘Table ‘wisan_db.student_info‘ doesn‘t exist‘
                 Skip_Counter: 0

4确保主从数据库数据一致

  • 此过程在开启主从复制功能之前完成

4.1主数据库

给数据库加上读锁

  • 开启一个终端用于上读锁
  • 当退出mysql时表示解锁
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.01 sec)
##其他终端更新数据时会卡住,直到解锁才会继续处理
mysql> insert into wisan_db.student_info(name,age) value(‘world‘,null);

全备主库

[root@vm1 ~]# mysqldump -uroot -p123456 --all-databases > /opt/database-backup/all-20201029.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@vm1 ~]# ls /opt/database-backup/
all-20201029.sql

发送给从数据库

[root@vm1 ~]# scp /opt/database-backup/all-20201029.sql root@192.168.225.130:/root/
root@192.168.225.130‘s password: 
all-20201029.sql             

解除锁表状态

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

mysql> quit
Bye
[root@vm1 ~]# 

4.2从数据库

恢复主库全备

[root@vm3 ~]# mysql -uroot -p123456 < /root/all-20201029.sql 
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@vm3 ~]# mysql -uroot -p123456 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| country            |
| mysql              |
| performance_schema |
| sys                |
| wisan_db           |
+--------------------+

mysql> select * from wisan_db.student_info;
+----+-------+------+
| id | name  | age  |
+----+-------+------+
|  1 | wisan |   18 |
|  2 | fyj   |   17 |
|  3 | flora |   19 |
|  4 | wang  |   20 |
|  5 | hello | NULL |
+----+-------+------+
5 rows in set (0.00 sec)

mysql> select * from wisan_db.student_score;
Empty set (0.00 sec)



以上是关于mysql-主从复制的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 主从复制与读写分离(原理深刻,过程详细,值得一看)

MySQL主从复制与读写分离

MySQL主从复制及读写分离实际部署与验证

MySQL主从复制及读写分离实际部署与验证

mysql实现主从复制/主从同步

MySQL主从复制以及读写分离(❤❤❤❤含理论和实验❤❤❤❤大家中秋快乐!㊗)