MySQL主从模式及配置

主服务器:192.168.20.239

从服务器:192.168.20.176

主从原理

主节点

1、当主节点上进行 insert、update、delete 操作时,会按照时间先后顺序写入到 binlog 中;
2、当从节点连接到主节点时,主节点会创建一个叫做 binlog dump 的线程;

3、一个主节点有多少个从节点,就会创建多少个 binlog dump 线程;

4、当主节点的 binlog 发生变化的时候,也就是进行了更改操作,binlog dump 线程就会通知从节点 (Push模式),并将相应的 binlog 内容发送给从节点;

从节点

当开启主从同步的时候,从节点会创建两个线程用来完成数据同步的工作。

I/O线程: 此线程连接到主节点,主节点上的 binlog dump 线程会将 binlog 的内容发送给此线程。此线程接收到 binlog 内容后,再将内容写入到本地的 relay log。

SQL线程: 该线程读取 I/O 线程写入的 relay log,并且根据 relay log 的内容对从数据库做对应的操作。

 

主从配置一般都是和读写分离相结合,主服务器负责写数据,从服务器负责读数据,并保证主服务器的数据及时同步到从服务器。

 

一、配置主服务器:

1:在mysql下找到my.ini文件,一般在 C:\ProgramData\MySQL\MySQL Server 5.7

在其[mysqld] 下添加主服务器端配置:

#服务器 id
server-id=1
#二进制文件存放路径
log-bin=C:\ProgramData\MySQL\MySQL Server 5.7\Data\mysql-bin
#待同步的数据库  (如果这一行没有,那么就是针对所有的不用忽略的数据库进行同步)
#binlog-do-db=test_db
#忽略不同步的数据库,这个可以不用写
#binlog-ignore-db=information_schema
#忽略不同步的数据库,这个可以不用写
#binlog-ignore-db=mysql

注意,上面的mysql-bin 并不是指一个文件夹,而是指 存放为二进制数据

 

2:保存my.ini文件,重启数据库,然后会在C:\ProgramData\MySQL\MySQL Server 5.7\Data 下看到 mysql-bin.index 文件和 mysql-bin.000001 文件;

3:连接主数据库

mysql -u root -p123456

4:给要连接的从服务器设置权限:(注意下面的 单引号  分号 )

grant replication slave,reload,super on *.* to 'backup'@'192.168.20.%' identified by '123456';

注释:  给主机192.168.20.%添加权限,用户名:backup,密码:123456;(只需输入一次就可以了)

    *.* 表示任意数据库中的任意表,'192.168.20.%' 表示只允许192.168.20.··网段的“从”访问“主” 的数据库

    如果你把字符,单引号或者是分号漏掉了,那么运行会没有反应的,如果运行成功,会显示 query ok

mysql> use mysql;
mysql> select user from user;
+---------------+
| user          |
+---------------+
| test          |
| backup        |
| mysql.session |
| mysql.sys     |
| root          |
+---------------+
#查看用户发现多了backup

实际就是在mysql中添加一个backup的 slave 账号,并授权给从服务器。创建backup用户,并授权给192.168.20.··使用。

 

 5:输入命令 show master status;       # 找到File 和 Position 的值记录下来; (如果你不小心把主服务器上的数据库删除了,然后重新添加了一个同名的,但是这里的position 是会改变的,一定要注意

 6: 导出主数据库的数据 

mysqldump -u root -p123456 --databases test_db > test_db.mysql

7:把导出的sql语句,导入从数据库

方法一:
mysql>source F:\dir\test_db.mysql
方法二:
先创建DB,然后:mysql -uroot -p123456 test_db < test_db.mysql

这样从服务器上也有了 test_db 这个数据库了 

 

二、配置从服务器:

1:在mysql下找到my.ini文件,在其[mysqld] 下添加从服务器端配置:

#服务器 id ,不能和主服务器一致
server-id=2
#同步的数据库(需要备份的数据库名),不写本行 表示 同步所有数据库
#replicate-do-db=test_db
#忽略不同步的数据库,这个可以不用写
#binlog-ignore-db=information_schema
#忽略不同步的数据库,这个可以不用写
#binlog-ignore-db=mysql
#忽略不同步的数据库,这个可以不用写
#binlog-ignore-db=test

2:保存my.ini文件,重启从数据库,在mysql5.1以上版本中是不支持1中master设置的,如果添加了master设置,数据库就无法重启了(这个可能是针对以前的低于5.1的数据库的,反正我们没有用到那么低的,所以不用管什么 master设置);

 

3:用上面分配的账号backup,尝试连接主数据库,成功

mysql -ubackup -p123456 -h192.168.20.239

4:重新打开一个dos界面,用管理员账号连接从数据库

mysql –uroot –p123456

修改对主数据库的连接的参数:

mysql> change master to master_host='192.168.20.239',master_user='backup',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=154;

ps:可能会报一个错误,大概的意思是说slave线程正在运行,不能设置,这样的话,执行mysql> stop slave; 停止slave线程,然后再设置连接的参数;

设置后,可以执行命令查看状态,Master_User: backup 就是刚刚的账号

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 192.168.20.239
                  Master_User: backup
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: DESKTOP-P02RV6K-relay-bin.000019
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: No
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1258
              Relay_Log_Space: 308
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 1236
                Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: a2085118-c063-11ec-a4a8-00090faa0001
             Master_Info_File: C:\ProgramData\MySQL\MySQL Server 5.7\Data\master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp: 220508 16:56:41
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.00 sec)

注意:上面的IO线程启动失败

Slave_IO_Running: No
错误信息 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

 原因:一方面是因为网络通信的问题,也有可能是日志读取错误的问题。因为我是重新设置的,所以可能是读取顺序的错误。

解决办法:

在 slave 执行 mysql> stop slave

在 master 执行 mysql> show master status;
刷新日志:mysql> flush logs;
因为刷新日志file的位置会+1,即File变成为:mysqld-bin.000002

马上到 slave 执行
mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysqld-bin.000002',MASTER_LOG_POS=154;
mysql> slave start;
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.20.239
                  Master_User: backup
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 154
               Relay_Log_File: DESKTOP-P02RV6K-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
******************************************************

Slave_IO_Running: Yes               这个表示:连接到主库,并读取主库的日志到本地,生成本地日志文件. yes表示  网络正常

Slave_SQL_Running: Yes             这个表示:读取本地日志文件,并执行日志里的SQL命令。  yes表示  表结构正常

 

5:在 master 中添加一行数据,发现 slave 中也自动增加了,并且Position保持一致。

 

6:使用 show processlist 语句可查看线程状态

主数据库上:可以看到线程Id=5的 State 是 「Master has sent all binlog to slave; waiting for more updates」,说明同步线程一直在运行中。

mysql> show processlist;
+----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User   | Host                  | db      | Command     | Time | State                                                         | Info             |
+----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+
|  2 | root   | localhost:11714       | test_db | Query       |    0 | starting                                                      | show processlist |
|  5 | backup | DESKTOP-P02RV6K:50511 | NULL    | Binlog Dump | 2315 | Master has sent all binlog to slave; waiting for more updates | NULL             |
+----+--------+-----------------------+---------+-------------+------+---------------------------------------------------------------+------------------+

从数据库上:

mysql> show processlist;
+----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host            | db      | Command | Time | State                                                  | Info             |
+----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+
|  6 | root        | localhost:58744 | test_db | Query   |    0 | starting                                               | show processlist |
|  9 | system user |                 | NULL    | Connect | 2230 | Waiting for master to send event                       | NULL             |
| 10 | system user |                 | NULL    | Connect |  858 | Slave has read all relay log; waiting for more updates | NULL             |
+----+-------------+-----------------+---------+---------+------+--------------------------------------------------------+------------------+

 

三、可能出问题的地方

1:开始一定要把数据库数据同步,保证数据一致性。

2:如果Slave_IO_Running: NO 那么要看看是不是  (1) A有账户在用dos界面在登陆数据库而没有退出 (2) A数据库的postion和file有改变,而B里面change的时候,还是用的以前的数据?

3:主库不小心死机,重启之后发现主库数据更新,但是从库不执行,造成了主从的数据不同步。但是在从上面查看 Slave_IO_Running 和  从库的状态,都是正常的。这个时候要注意在主库看看 show master status  看看postion和file是不是和从库一致的,我就发现我的主库死机之后再次开机就不一样了。这个时候在从库执行  

CHANGE MASTER TO MASTER_HOST='192.168.20.239',MASTER_USER='backup',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=154

但是这里还是有个问题,虽然这个时候,主从可以开始同步了,但是由于这中间,如果不是及时发现,那么主从的数据还是会有差异的,那这个怎么解决呢?  答案是,只能重新设置主从。

4:如果我在主里面  delete  from  xx表  那么在从里面,到底是读出主里面删除了哪些行,进而对从进行删除?还是直接也是和主一样,运行了 delete from xx呢?答案是后者,从会像主一样,直接运行 delete from  xx 。所以如果你是有上面3这个问题发生(主从数据不同步了),后面再进行了其他操作的话,会越来越不同步的,所以赶紧重新做主从

5:从库挂了怎么办

在主服务的 binlog dump 线程将指定的 binlog 信息发给从服务时,除了日志内容,还包括本次发送内容在主服务端的 bin-log 日志文件名称以及位置信息。

从服务的 I/O 线程接收到信息后将日志内容写入realy-log 文件(mysql-relay-bin.xxxxxx)的末端,并将读取到的主服务端的 bin-log 的文件名和位置记录到 master-info 中(通过 show slave status 中的 Master_Info_File 字段可以看到 master.info 保存的位置),以便下一次读取时能告诉主服务从哪里开始同步。

从服务的 SQL 线程检测到 realy-log 新增了内容后,解析日志文件生成对应的 sql 语句,并应用这些 sql 到数据库,保证主从数据一致性。

所以,即使从库挂掉了,因为有 master.info 记录了上一次同步的位置,只要同步服务再次启动,那就可以从上次同步的位置继续增量同步了。

 

参考资料

1:公众号[古时的风筝]MySQL主从配置和读写分离 https://www.cnblogs.com/fengzheng/p/13401783.html

2:windows 下mysql 主从库的配置 https://www.cnblogs.com/joeylee/archive/2013/01/24/2875515.html

 

posted @ 2022-05-08 18:06  Brickert  Views(1146)  Comments(0Edit  收藏  举报