mysql搭建gtid和binarylog日志主从节点

概述

  • mysql搭建主从的方式有多种
  • bingarylog日志主从
  • GTID主从

binary log方式实现方式

  • 为master分配一个唯一id (server-id)
  • 开启log-bin选项
  • 重启服务器
  • 创建一个专门用于复制的用户(非必要,但更安全)
  • 锁表,禁止数据库写入数据
  • 获取bin log日志的名称和位置

master配置

  • 修改master配置文件 mysql.cnf
    [mysqld]
    log-bin      = mysql.bin   #binary log日志的前缀名称,可随意
    server-id    = 1
    bind-address = 0.0.0.0   # 让mysql接收外部网络连接
    # 由于MySQL默认只监听127.0.0.1,因此无法被外部网络连接,因此要把它改为0.0.0.0。
    binlog-do-db=lmk # 主从同步时需要同步哪个库
    binlog-ignore-db=mysql # 主从同步不需要同步哪个库 mysql有敏感信息
  • 修改完成后先重启服务器,否则后面的步骤无法顺利进行
    # 创建一个专门用于复制,且没有其他权限的用户
    mysql> create user 'repl'@'%' identified by 'repl';  #创建用户
    mysql> grant replication slave on *.* to 'repl'@'%';  #只授予复制权限
  • 接下来就要锁表,禁止数据库被修改,目的是获取当前数据库的日志名称和时间位置
    mysql> flush tables with read lock;
    # 输入命令后不能退出mysql,以保持锁的状态
  • 数据库锁定后,接下来就是最重要的一步,获取日志的名称和位置信息
    mysql> show master status\G
    *************************** 1. row ***************************
                 File: mysql-bin.000002
             Position: 334
         Binlog_Do_DB: 
     Binlog_Ignore_DB: 
    Executed_Gtid_Set: 
    1 row in set (0.00 sec)
    
    # master准备完毕

slave配置

  • 和master服务器一样,slave服务器也要分配一个唯一的id。
  • 重启服务器
  • 设置主服务器的相关信息
  • 开启slave工作线程
  • 检查slave服务器的状态
    修改slave服务器配置文件mysql.cnf
    [mysqld]
    server-id = 2
    和master服务器相比,slave服务器目前只需要添加一个唯一的id即可。
  • 重启服务器
    mysql> stop slave; # 先停止slave 进行配置
    mysql> change master to MASTER_HOST='192.168.100.200',\ # 指定mysql主ip
                            MASTER_USER=’repl',\  # 指定mysql主创建的用户
                            MASTER_PASSWORD='repl',\  # 指定mysql主创建的用户密码
                            MASTER_LOG_FILE='mysql-bin.000002',\  #主服务配置最后一步获得的信息
                            MASTER_LOG_POS=334;     #同样是主服务器配置最后一步获得的信息
                            # 后两个是通过 show master status\G 获取的
    mysql> start slave; # 开启从服务器
  • 顺利的话主从就完成了,可以通过以下命令查看是否配置成功
    mysql> show slave status\G
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.88.204
                      Master_User: repl
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000002
              Read_Master_Log_Pos: 334
                   Relay_Log_File: ubunt-host1-relay-bin.000002
                    Relay_Log_Pos: 500
            Relay_Master_Log_File: mysql-bin.000002
                 Slave_IO_Running: Yes # 查看这里是否是yes
                Slave_SQL_Running: Yes # 查看这里是否是yes
                         ...
                       Last_Errno: 0
                       Last_Error: 
                         ...
                 Master_Server_Id: 1
                      Master_UUID: bd9480c5-6f83-11e8-a486-000c29e23e48
                 Master_Info_File: /var/lib/mysql/master.info
                        SQL_Delay: 0
              SQL_Remaining_Delay: NULL
          Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
                       ...
    1 row in set (0.00 sec)

配置GTID主从

  • GTID实际上是对传统基于binary log的复制进行了增强,在binary log复制中,我们必须手动跟踪主服务器的日志名称和位置,但是在GTID工作方式下面,我们无需跟踪这两个值,取而代之的是有mysql自动跟踪它们,并使用GTID来标记哪些事务已经被处理,哪些还没有被处理
  • 优点:

    相同的GTID事务不会被重复处理,好处是可以最大限度的确保数据一致性

组成部分

  • 一部分是服务器的 UUID
  • 另一部分是事务ID
  • 假如服务器的UUID是 bd9480c5-6f83-11e8-a486-000c29e23e48 那么它和第一个事务的GTID组成如下
    bd9480c5-6f83-11e8-a486-000c29e23e48:1

配置过程

  • 在GTID方式配置过程中,主从服务器都应该确保开启了log-bin选项,还有另外两个新增选项 gitd-modeenforce-gtid-consistency

  • 为master和slave服务器分配唯一的server id

  • master和slave都要开启log-bin选项

  • master和slave都要开启gtid-mode和enforce-gtid-consistency选项

  • slave服务器开启日志自动跟踪

master配置

  • 修改配置文件
    [mysqld]
    server-id=1   #除了server-id不同外,其他配置主从都相同
    log-bin=mysql-bin
    
    gtid-mode = on
    enforce-gtid-consistency = on
  • 重启服务器

slave配置

  • 修改配置文件
    [mysqld]
    server-id=2   #除了server-id不同外,其他配置主从都相同
    log-bin=mysql-bin
    
    gtid-mode = on
    enforce-gtid-consistency = on
  • 指定master位置
    mysql> stop slave;
    mysql> change master to MASTER_HOST='192.168.100.200',\ # master hostz地址
                            MASTER_USER=’repl',\ # master创建的用户
                            MASTER_PASSWORD='repl',\ # master创建用户的密码
                            MASTER_AUTO_POSITION=1#自动跟踪日志名称和位置
    mysql> start slave;
  • 上面是从零开始配置的GTID主从,如果之前配置了binary log 主从 则命令就更简单了
    mysql> change master to MASTER_AUTO_POSITION=1#自动跟踪日志名称和位置
    # 只需要配置一下该字段即可
  • 测试是否成功
    # master
    mysql> show master status\G
    *************************** 1. row ***************************
                 File: mysql-bin.000003
             Position: 340
         Binlog_Do_DB: 
     Binlog_Ignore_DB: 
    Executed_Gtid_Set: bd9480c5-6f83-11e8-a486-000c29e23e48:1
    1 row in set (0.00 sec)
  • 会发现Executed_Gtid_Set多了一个值:bd9480c5-6f83-11e8-a486-000c29e23e48:1,这个值表示这个事务是当前的一个事务。
  • 同样登录 slave 查看一下
    mysql> show slave status\G
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.88.204
                      Master_User: repl
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000003
              Read_Master_Log_Pos: 340
                   Relay_Log_File: ubunt-host1-relay-bin.000002
                    Relay_Log_Pos: 553
            Relay_Master_Log_File: mysql-bin.000003
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                       ...
                       Last_Errno: 0
                       Last_Error: 
                       ...
                 Master_Server_Id: 1
                      Master_UUID: bd9480c5-6f83-11e8-a486-000c29e23e48
                 Master_Info_File: /var/lib/mysql/master.info
                        SQL_Delay: 0
              SQL_Remaining_Delay: NULL
          Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
                       ...
               Retrieved_Gtid_Set: bd9480c5-6f83-11e8-a486-000c29e23e48:1
                Executed_Gtid_Set: bd9480c5-6f83-11e8-a486-000c29e23e48:1
                    Auto_Position: 1
             Replicate_Rewrite_DB: 
                     Channel_Name: 
               Master_TLS_Version: 
    1 row in set (0.00 sec)
  • 和之前相比,从服务器的输出信息也有点不一样了
  • Retrieved_Gtid_Set和Executed_Gtid_Set都填充了值
  • Auto_Position变成了1

注意的问题

添加更多的从服务器

  • 有时候我们希望配置多台从服务器。如果是新建立的主从环境,没有什么数据,那么无论多少从服务器,搭建方式和上面说的没有什么两样。重点是,如果在已经运行了一段时间的主从环境中添加更多的从服务器,那么这台从服务器的配置就有点不一样。原因是:在主从配置的过程中,我们需要对服务器进行锁表操作,也就是说,任何数据都不可以继续写入,且持续的时间有可能会很长,在生产环境下,基本上是不允许的。

  • 也就是说,我们不能在主服务器上下手,相反,应该在已经存在的从服务器下手,基本过程如下

  • 停止旧slave服务器的MySQL服务

  • 把旧的slave服务器上的数据复制到新的从服务器里

  • 为新服务器分配唯一的server-id和开启其他选项

  • 重启服务器

详细过程

  • 第一步:我们需要停止旧的slave服务器的MySQL
    root@slave1:~# mysqladmin -u root -p shutdown
  • 第二步:把旧从库的数据复制到新的从库中
  • 可以有多种方式复制数据,例如先使用mysqldump备份旧的数据,然后在新库中还原,也可以直接打包原始数据,然后复制到新库的对应目录下面。这里我选择了后者:
    root@slave1:~# cd /var/lib/mysql
    root@slave1:/var/lib/mysql# ls
    auto.cnf         ibdata1      master.info       mysql-bin.index     replication    slave1-relay-bin.000002
    debian-5.7.flag  ib_logfile0  mysql             performance_schema  sys            slave1-relay-bin.index
    ib_buffer_pool   ib_logfile1  mysql-bin.000001  relay-log.info      slave1-relay-bin.000001
    
    # 接下来使用tar命令对这些数据进行打包操作:
    root@slave1:/var/lib/mysql# tar -zcvf data.tar.gz2 .
  • 打包完成后,我们就可以把数据复制到新的从库里面,这里我选择了使用scp命令,如果数据非常大的话请选择其他方案。
    root@slave1:/var/lib/mysql# scp data.tar.gz2 root@192.168.88.217:/var/lib/mysql/  #复制数据到远程主机的/var/lib/mysql目录
    The authenticity of host '192.168.100.200 (192.168.100.200)' can't be established.
    ECDSA key fingerprint is SHA256:iAoWxPJ22h3p9T9grTgcC5lqpB1Q1Tw7wjznkUab0HI.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.100.200' (ECDSA) to the list of known hosts.
    root@192.168.88.217's password: 
    data.tar.gz2                                    100% 1443KB   1.4MB/s   00:00
    
    # 复制完后到新服务器中解压文件
    root@slave2:~# cd /var/lib/mysql
    root@slave2:/var/lib/mysql# ls
    auto.cnf  data.tar.gz2  debian-5.7.flag  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ibtmp1  mysql  performance_schema  sys
    root@slave2:/var/lib/mysql# tar -zxf data.tar.gz2
  • 第三步:配置mysqld.cnf文件 这里配置的是新的从服务器
    [mysqld]
    server-id = 3
    gtid-mode = on
    enforce-gtid-consistency = on
  • 重启服务器

发现异常

  • 异常1

    在新的服务器使用show slave status查看结果:

    mysql> show slave status\G
    *************************** 1. row ***************************
                   Slave_IO_State: 
                      Master_Host: 192.168.88.204
                      Master_User: repl
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000003
              Read_Master_Log_Pos: 340
                   Relay_Log_File: slave1-relay-bin.000002
                    Relay_Log_Pos: 553
            Relay_Master_Log_File: mysql-bin.000003
                 Slave_IO_Running: No
                Slave_SQL_Running: No
                       ...
                       Last_Errno: 1872
                       Last_Error: Slave failed to initialize relay log info structure from the repository
                     Skip_Counter: 0
                       ...
                   Last_SQL_Errno: 1872
                   Last_SQL_Error: Slave failed to initialize relay log info structure from the repository
      Replicate_Ignore_Server_Ids: 
                 Master_Server_Id: 0
                      Master_UUID: bd9480c5-6f83-11e8-a486-000c29e23e48
                 Master_Info_File: /var/lib/mysql/master.info
  • 虽然MySQL服务可以正常运作,但slave线程却没有如我们期待的正常开启,而且还发现了错误

    Last_Errno: 1872
    Last_Error: Slave failed to initialize relay log info structure from the repository
  • 通过查看MySQL的日志文件,发现有类似下面的错误信息:/var/log/mysql/error.log日志文件部分输出

    2018-06-16T07:54:49.511960Z 0 [Warning] Neither --relay-log nor --relay-log-index were used; so replication may break when this MySQL server acts as a slave and has his hostname changed!! Please use '--relay-log=slave2-relay-bin' to avoid this problem.
    2018-06-16T07:54:49.526580Z 0 [ERROR] Failed to open the relay log './slave1-relay-bin.000002' (relay_log_pos 553).
    2018-06-16T07:54:49.526659Z 0 [ERROR] Could not find target log file mentioned in relay log info in the index file './slave2-relay-bin.index' during relay log initialization.
  • 原因在于,默认情况下,slave线程会使用主机名-relay-bin的方式保存日志文件, 而新库的所有数据文件都是由旧库那里复制过来的,包括从库的一些配置文件,这就导致配置信息中的主机名冲突。

解决办法

  • 解决办法其实错误日志中已经给出,就是使用–relay-log选项明确指定relay-log的名称
    # 修改mysqld.cnf,添加relay-log选项:
    [mysqld]
    server-id = 3
    gtid-mode = on
    enforce-gtid-consistency = on
    relay-log = slave1-releay-bin  #使用旧主机的relay-log
  • 当然,也可以不添加relay-log选项,解决办法如下:
  • 把旧slave的slave1-relay-bin.index中的内容追加到新slave的slave2-relay-bin.index文件中
  • 重启新slaveMySQL服务
    root@slave2:/var/lib/mysql# ls
    ai               ib_buffer_pool  ibtmp1         mysql-bin.index     sys    slave2-relay-bin.000001
    auto.cnf         ibdata1         master.info    performance_schema  slave1-relay-bin.000005  slave2-relay-bin.index
    data.tar.gz2     ib_logfile0     mysql             relay-log.info   slave1-relay-bin.000006
    debian-5.7.flag  ib_logfile1     mysql-bin.000001  replication      slave1-relay-bin.index
    root@slave2:/var/lib/mysql# cat slave1-relay-bin.index >> slave2-relay-bin.index
  • 异常2
  • 修改后重启服务器,再次使用show slave status检查,发现另一个问题,错误如下:
    Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'A slave with the same server_uuid/server_id as this slave has connected to the master; the first event '' at 4, the last event read from './mysql-bin.000003' at 493, the last byte read from './mysql-bin.000003' at 493.'
  • 意思是已经有相同uuid的服务器连接到master,造成这种错误的原因和上面的一样。服务器的uuid其实是保存在数据目录的auto.cnf文件里面,在复制数据到新slave的时候,把这个auto.cnf文件也复制到新的slave中,因此,两个slave的uuid就发生了冲突。

解决办法

  • 如果MySQL发现没有auto.cnf文件,就会重新生成一个,也就是说,这要把发生冲突的auto.cnf文件删除,服务器就会生成一个新的uuid。所以,只要把这个文件删除,然后重启服务器就OK了。

  • 全部问题都解决之后,在master中运行如下命令:

    mysql> show slave hosts;
    +-----------+------+------+-----------+--------------------------------------+
    | Server_id | Host | Port | Master_id | Slave_UUID                           |
    +-----------+------+------+-----------+--------------------------------------+
    |         3 |      | 3306 |         1 | d77f4132-7142-11e8-b21c-000c29c59da1 |
    |         2 |      | 3306 |         1 | 46108417-6f84-11e8-a559-000c29c7aaa0 |
    +-----------+------+------+-----------+--------------------------------------+
    2 rows in set (0.00 sec)
    # 两个slave都被master识别出来。

小结


本博客所有文章是以学习为目的,如果有不对的地方可以一起交流沟通共同学习 邮箱:1248287831@qq.com!