zoukankan      html  css  js  c++  java
  • 【MySQL】主从复制

    纸上得来终觉浅,绝知此事要躬行。

    主从复制

    change master to master_host='172.17.0.2', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 1547, master_connect_retry=30;
    

    纸上得来终觉浅,绝知此事要躬行。

    概述

    复制是指将主数据库的DDL DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。

    MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。

    优势

    MySQL 复制的优点主要包含以下三个方面:

    • 主库出现问题,可以快速切换到从库提供服务。

    • 可以在从库上执行查询操作,从主库中更新,实现读写分离,降低主库的访问压力。

    • 可以在从库中执行备份,以避免备份期间影响主库的服务。

    原理

    在详细介绍如何设置复制之前,我们先看看MySQL实际上是如何复制数据的,总的来说,复制分为三个步骤:

    1. 在主库上把数据更改记录到二进制日志(Binary Log)中。
    2. 备库将主库上的日志复制到自己的中继日志(Relay Log)中。
    3. 备库重做中继日志中的日志,把更改应用到自己的数据库上,已达到数据的一致性。

    拆分这三步,具体过程如下:

    第一步在主库上记录二进制文件。在每次准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中。MySQL会按照事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志之后主库会告诉存储引擎提交事务。即:在事务提交之前记录二进制日志

    第二步,从库将主库的二进制日志复制到其本地的中继日志。首先从库会启动一个工作线程称为I/O线程,该线程跟主库建立一个普通的客户端连接,然后在主库上启动一个特殊的二进制转储(binlog dump)线程,这个二进制转储线程会读取主库上二进制日志事件,他不会对事件进行轮询。如果该线程追赶上了主库,他将进入睡眠状态,直到主库发送信号量通知从库有新的事件才会被唤醒,然后线程将接受到的事件记录到中继日志。

    第三步,从库中的线程从中继日志中读取事件并在从库执行,从而实现从库数据的更新。

    配置

    Master配置

    1. 查看MySQL默认配置文件
    mysql --help|grep 'my.cnf'
    
    1. 选择一个配置文件输入以下配置信息
    # 必须,表示mysql配置文件
    [mysqld]
    
    # mysql 服务ID,保证整个集群环境中唯一
    server-id=1
    
    # mysql binlog 日志的存储路径和文件名
    log-bin=/var/lib/mysql/mysqlbin
    
    # 错误日志,默认已经开启
    # log-err
    
    # mysql的安装目录
    # basedir
    
    # mysql的临时目录
    # tmpdir
    
    # mysql的数据存放目录
    # datadir
    
    # 是否只读,1 代表只读, 0 代表读写
    read-only=0
    
    # 忽略的数据, 指不需要同步的数据库
    binlog-ignore-db=mysql
    
    # 指定同步的数据库
    # binlog-do-db=db01
    
    1. 保存完毕之后,重启服务
    service mysql restart
    
    1. 创建同步数据的账户,并且进行授权操作
    grant replication slave on *.* to '从库用户名'@'从库服务器地地址' identified by '密码';	
    
    # 例如:grant replication slave on *.* to 'root'@'192.168.192.131' identified by 'root';	
    
    flush privileges;
    
    1. 查看log-bin是否已打开
    mysql> show variables like '%log_bin%';
    +---------------------------------+-------------------------------+
    | Variable_name                   | Value                         |
    +---------------------------------+-------------------------------+
    | log_bin                         | ON                            |
    | log_bin_basename                | /var/lib/mysql/mysqlbin       |
    | log_bin_index                   | /var/lib/mysql/mysqlbin.index |
    | log_bin_trust_function_creators | OFF                           |
    | log_bin_use_v1_row_events       | OFF                           |
    | sql_log_bin                     | ON                            |
    +---------------------------------+-------------------------------+
    6 rows in set (0.00 sec)
    
    1. 查看master状态
    mysql> show master status;
    +-----------------+----------+--------------+------------------+-------------------+
    | File            | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +-----------------+----------+--------------+------------------+-------------------+
    | mysqlbin.000001 |      154 |              | mysql            |                   |
    +-----------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)
    
    # File : 从哪个日志文件开始推送日志文件 
    # Position : 从哪个位置开始推送日志
    # Binlog_Ignore_DB : 指定不需要同步的数据库
    

    Slave配置

    1. 与Master一样查找配置文件,输入以下内容
    # mysql服务端ID,唯一
    server-id=2
    
    # 指定binlog日志
    log-bin=/var/lib/mysql/mysqlbin
    
    1. 保存完毕之后,重启服务
    service mysql restart
    
    1. 登录数据库,输入以下命令
    change master to master_host= '192.168.192.130', master_user='主库用户名', master_password='主库密码', master_log_file='mysqlbin.000001', master_log_pos=154;
    

    指定当前从库对应的主库的IP地址,用户名,密码,从哪个日志文件开始的那个位置开始同步推送日志。

    1. 开启同步操作
    start slave;
    show slave status;
    

    1. 停止同步操作
    stop slave;
    

    测试配置同步

    • 在主库中创建数据库,创建表,并插入数据 :
    create database db01;
    
    user db01;
    
    create table user(
    	id int(11) not null auto_increment,
    	name varchar(50) not null,
    	sex varchar(1),
    	primary key (id)
    )engine=innodb default charset=utf8;
    
    insert into user(id,name,sex) values(null,'Tom','1');
    insert into user(id,name,sex) values(null,'Trigger','0');
    insert into user(id,name,sex) values(null,'Dawn','1');
    
    • 在从库中查询数据,进行验证 :

    在从库中,可以查看到刚才创建的数据库:

    在该数据库中,查询user表中的数据:

    基于Docker搭建

    本次通过Docker搭建是利用Docker开启多个MySQL实例进行搭建,不需要额外的虚拟机,配置方便。服务分配如下:

    服务器 端口 启动
    172.17.0.2 5566 mysql-master
    172.17.0.3 5577 mysql-slave1
    172.17.0.4 5588 mysql-slave2

    主服务器搭建

    1.首先在172.17.0.2拉取docker镜像,我们这里使用5.7版本的MySQL

    $ docker pull mysql:5.7
    $ docker images
    REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
    docker.io/mysql       5.7                 e1e1680ac726        7 months ago        373 MB
    

    2.创建一个目录,用于宿主机与Docker容器建立数据卷

    $ mkdir -p /data/docker/mysql-master/
    

    3.在当前目录中创建配置文件my.cnf,次文件要映射到MySQL的docker容器中的配置文件,文件中加入内容如下:

    [mysqld]
    skip-name-resolve
    server-id=1       
    log-bin=mysql-bin   
    binlog-do-db=tx_db
    binlog-ignore-db = mysql
    binlog-ignore-db = information_schema
    

    4.创建主机容器,Master对外映射的端口是5566

    $ docker run -p 5566:3306 --name mysql-master -v /data/docker/mysql-master:/etc/mysql/mysql.conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    

    5.查看容器运行情况

    $ docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
    5d74def70b04        mysql:5.7           "docker-entrypoint.s…"   2 hours ago         Up 2 hours          33060/tcp, 0.0.0.0:5566->3306/tcp   mysql-master
    

    6.在Master数据库创建数据同步用户

    CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
    
    GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
    
    flush privileges;
    

    从服务器搭建

    1.创建目录,用于宿主机与Docker容器建立数据卷

    $ mkdir -p /data/docker/mysql-slave1/
    $ mkdir -p /data/docker/mysql-slave2/
    

    2.分别在两个目录中创建配置文件my.cnf

    [mysqld]
    skip-name-resolve
    server-id=   2
    log-bin=mysql-bin  
    replicate-do-db=tx_db 
    binlog-ignore-db = mysql
    binlog-ignore-db = information_schema
    

    3.创建主机容器,Slave1对外映射的端口是5577,Slave2对外映射的端口是5588

    $ docker run -p 5577:3306 --name mysql-slave1 -v /data/docker/mysql/mysql-slave1:/etc/mysql/mysql.conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    
    $ docker run -p 5588:3306 --name mysql-slave2 -v /data/docker/mysql/mysql-slave2:/etc/mysql/mysql.conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    

    4.查看容器运行情况

    $ docker ps -a
    

    5.登录从服务器

    docker exec -it [CONTAINER ID] /bin/bash
    

    6.查看主服务器状态

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

    7.登录数据库,输入以下命令

    方式一:容器内网访问

    master_host可以通过docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称|容器id查询。

    端口是3306

    change master to master_host='172.17.0.2', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000002', master_log_pos= 154, master_connect_retry=30;
    

    方式二:映射宿主机访问,master_host是宿主机IP,端口是对外映射端口

    change master to master_host='192.168.0.108', master_user='slave', master_password='123456', master_port=5566, master_log_file='mysql-bin.000002', master_log_pos= 154, master_connect_retry=30;
    
    • master_host :Master的地址,指的是容器的独立IP
    • master_port:Master的端口号,指的是容器的端口号
    • master_user:用于数据同步的用户
    • master_password:用于同步的用户的密码
    • master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
    • master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
    • master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒

    8.开启同步操作

    • 方式一连接登录:
    mysql> start slave;
    mysql> show slave statusG
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 172.17.0.2 --注意IP
                      Master_User: slave
                      Master_Port: 3306 --注意端口
                    Connect_Retry: 30
                  Master_Log_File: mysql-bin.000002
              Read_Master_Log_Pos: 154
                   Relay_Log_File: 2a42f09f6e2b-relay-bin.000002
                    Relay_Log_Pos: 320
            Relay_Master_Log_File: mysql-bin.000002
                 Slave_IO_Running: Yes  --IO线程启动
                Slave_SQL_Running: Yes --SQL线程启动
                  Replicate_Do_DB: tx_db --需要同步的数据库
                  ..............
    
    • 方式二连接登录:
    mysql> start slave;
    mysql> show slave statusG
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.0.108 --注意IP
                      Master_User: slave
                      Master_Port: 5566 --注意端口
                    Connect_Retry: 30
                  Master_Log_File: mysql-bin.000002
              Read_Master_Log_Pos: 154
                   Relay_Log_File: 2a42f09f6e2b-relay-bin.000002
                    Relay_Log_Pos: 320
            Relay_Master_Log_File: mysql-bin.000002
                 Slave_IO_Running: Yes --IO线程启动
                Slave_SQL_Running: Yes --SQL线程启动
                  Replicate_Do_DB: tx_db --需要同步的数据库
                  ................
    

    9.关闭同步

    stop slave;
    

    测试

    1.主服务器建库建表,添加数据

    mysql> create database tx_db default character set=utf8;
    
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | tx_db              |
    +--------------------+
    5 rows in set (0.00 sec)
    
    mysql> use tx_db;
    
    mysql> create table user(id int,name varchar(20));
    Query OK, 0 rows affected (0.50 sec)
    

    2.从服务器查询数据

    mysql> select * from user;
    +------+--------+
    | id   | name   |
    +------+--------+
    |    1 | ydongy |
    +------+--------+
    1 row in set (0.00 sec)
    
  • 相关阅读:
    第一次冲刺02
    第一次冲刺01
    Android源码分析(十四)PackageManagerService服务分析
    Android源码分析(十三)ActivityManagerService服务分析
    Android源码分析(十二)ServiceManager服务分析
    Serializable和Parcelable之序列化
    ViewPager 相关使用
    AIDL介绍以及简单使用
    Android 四大组件 (五) 第五大组件
    Android 源码分析(十一) 事件传递机制
  • 原文地址:https://www.cnblogs.com/ydongy/p/13094472.html
Copyright © 2011-2022 走看看