MySQL的主从同步

这里写图片描述

主从同步原理:

  1. Master中的数据改变会记录二进制日志(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看)
  2. 从服务器上生成两个线程,一个I/O线程,一个SQL线程

    • i/o线程去请求主库的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中;
      主库会生成一个 log dump线程,用来给从库 i/o线程传binlog;
    • SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;

半同步:对于一主多从的mysql架构中,主服务器接收到任意一台从服务器的数据同步完成,则认为数据同步成功。

数据库架构四大问

Q:主从架构中,不使用MySQL代理中,主的负责写,从负责读。

A:在LAMP的架构中,在php的代码上调用查询数据库的接口时,指向从服务器,如果需要插入数据,执行主服务器。

缺点:如果从服务器有多个,php代码写入比较困难。如果有多个从服务器,用php代码无法实现,真正的轮循


Q:如果想解决的上面的帮办,该怎么办。
A:使用MySQL主主同步。

双主模型:无法减轻写操作,第一台写了,第二台必定要同步数据,
如果多个客户端在两个主服务器上,同时写数据,会到值数据冲突,例如,表中的id是自动增长的,主、备都插入数据,会到导致主键冲突。


Q:主主架构无法解决IO的负载,如果业务足够大会导致主服务器上的消耗比较大。该如何解决。
A1:换更好的服务器,这当然是老板不愿意看到的。
A2:根据公司的业务,将不同的库方在不同的服务器上,(垂直拆分)如果拆分之后,如果有一个表的数据过大导致查询数据缓慢,可以对表进行拆分(水平拆分)


Q:这样IO的问题是解决了,但是新的问题又出现了,如果如果一个表中有1kw数据,分不到10台服务器上,如何才能查询到对应的数据,如果逐个查询,查询结果太过缓慢。
A:可以在这10台服务器前面增加路由,路由能根据客户的查询分配到后端的10台服务器,并将结果汇总发送给客户。


MySQL 5.5 之前主从同步比较简单
MySQL5.6 之后使用gtid(全局事务号)使mysql的复制更加安全,不会在多事务并行是产生混乱。mlti-thread replication(多线程复制)

配置MySQL复制基本步骤

master上配置

  1. 启动二进制日志

    log-bin=master-bin
    log-bin-index=master-bin.index
  2. 选择一个唯一的serverID

    server-id={0-25532}
  3. 创建具有复杂权限的用户

    replication slave   从主服务器上的二进制日志中复制事件的权限
    replication client  从主服务器上火相关信息的权限

slave上配置

  1. 启用中继日志

    relay-log=relay-log
    relay-log-index=
  2. 启动二进制日志(可选,如果只作为从服务器,可以关闭,但是如果作为从服务器的中转需要开启)

    log-bin=master-bin
    log-bin-index=master-bin.index
  3. 选择一个唯一的serverID

    server-id={0-25532}
    
  4. 连接至主服务器。并开始复制数据。

    mysql> change master to master_host='',master_port='',master_log_file='',master_log_pos='',master_user='',master_password='';
    
    mysql> start slave;
    或者
    mysql> start slave IO_thread;
    mysql> start slave SQL_thread;

实操

master上操作

修改配置文件/etc/my.cnf

[root@localhost ~]# vim /etc/my.cnf 
# 设置Innodb的存储引擎每个表使用一个存储空间
innodb_file_per_table=1

# 开启二进制日志,并设置二进制日志的所有名称
log-bin=master-bin
log-bin-index=master-bin.index

# 设置二进制日志的格式是混合模式
binlog_format=mixed

# 设置一个唯一的server-id
server-id= 1

重启mysql服务

[root@localhost ~]# service mysqld restart
Shutting down MySQL. SUCCESS! 
Starting MySQL.. SUCCESS!

授权从服务器拷贝二进制日志的用户

mysql> grant replication slave on *.* to 'repluser'@'192.168.10.144' identified by '123';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
slave服务器

注意:主从同步,如果主服务器上有数据,需要先将主服务器上的数据全部同步到从服务器上。

修改从服务器的配置文件

[root@localhost ~]# vim /etc/my.cnf 
innodb_file_per_table=1

# 开启relay-log
relay-log=relay-log
relay-log-index=relay-log.index

# 只有一个从服务器,可以不用记录二进制日志。如果作为二进制日志的从服务器需要开启二进制日志。
#log-bin=slave-bin
#log-bin-index=slave-bin.index
binlog_format=mixed

# 设置服务器的ID号,必须和主服务器不同。
server-id= 2

重启mysql服务

[root@localhost ~]# service mysqld restart
Shutting down MySQL. SUCCESS! 
Starting MySQL.. SUCCESS! 

在master上查看当前的二进制日志和站点

mysql> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |      338 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

在从服务器上设置连接主服务器的用户名、密码、二进制日志、二进制日志的站点。

mysql> change master to master_host='192.168.10.145',master_user='repluser',master_password='123',master_log_file='master-bin.000001',master_log_pos=338;
Query OK, 0 rows affected (0.06 sec)

查看从服务器的状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.10.145   主服务器的主机地址
                  Master_User: repluser   连接主服务器同步的用户名
                  Master_Port: 3306
                Connect_Retry: 60   如果连接不上每隔60s重试一次
              Master_Log_File: master-bin.000001  当前读取的主服务器的二进制位置
          Read_Master_Log_Pos: 338  主服务器的二进制日志位置
               Relay_Log_File: relay-log.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: No   从服务器的IO进程
            Slave_SQL_Running: No   从服务器的SQL进程
              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: 338    # 执行语句到达的站点
              Relay_Log_Space: 107
              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: NULL   #从服务器比至服务器慢的时间
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 0
1 row in set (0.00 sec)

启动从服务器,启动IO、SQL进程

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
确保从服务器无法修改,需要修改read_only

修改配置文件/etc/my.cnf

read_only=on  # 对于具有super权限的用户不生效

重启mysql服务

[root@localhost ~]# service mysqld restart
Shutting down MySQL. SUCCESS! 
Starting MySQL.. SUCCESS! 
mysql> show variables like 'read_only';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only     | ON    |
+---------------+-------+
1 row in set (0.00 sec)
重启mysql服务之后,从服务器的SQL、IO进程正常运行
[root@localhost ~]# cd /mydata/data/

# master.info中记录了连接主服务器的用户名、密码、端口、二进制日志问、二进制文件站点
[root@localhost data]# cat master.info 
18
master-bin.000001
423
192.168.10.145
repluser
123
3306
60
0

# relag-log.info中记录了具体使用的relay-log,以及现在的站点,还有主服务器的二进制日志以及二进制日志的站点。
[root@localhost data]# cat relay-log.info 
./relay-log.000004
254
master-bin.000001
423
为确保事务安全在master服务器上设置sync_binlog

修改配置文件/etc/my.cnf中sync_binlog日志,

sync_binlog=1  # 保证主服务器上的事务提交之后,能第一时间写到二进制日志中确保主服务器中的数据同步到从服务器上,防止主服务器的 事务提交之后,没有写入二进制日志,中途主服务器挂掉,事务执行的数据无法同步。
[root@localhost ~]# service mysqld restart
Shutting down MySQL. SUCCESS! 
Starting MySQL.. SUCCESS! 

测试

主服务器上创建数据库

mysql> create database studb;
Query OK, 1 row affected (0.06 sec)

从服务器上查看数据库。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| studb              |
| test               |
+--------------------+
5 rows in set (0.06 sec)

半同步复制

注:在同步的基础上配置。

使用源码安装的mysql中,有Google提供的半同步模块。在安装目录/usr/local/mysql/lib/plugin中有semisync_slave.so和semisync_master.so模块,semisync_master.so 是主服务器上需要安装的模块,semisync_slave.so是从服务器上需要安装的模块。

[root@localhost plugin]# pwd
/usr/local/mysql/lib/plugin
[root@localhost plugin]# ls
adt_null.so  auth_socket.so       daemon_example.ini  ha_example.so    libdaemon_example.so  qa_auth_client.so     qa_auth_server.so   semisync_slave.so
auth.so      auth_test_plugin.so  debug               ha_federated.so  mypluglib.so          qa_auth_interface.so  semisync_master.so

主服务器上操作

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.29 sec)

mysql> show global variables like '%rpl%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_recovery_rank                  | 0     |
| rpl_semi_sync_master_enabled       | OFF   | #设置是否开启半同步复制
| rpl_semi_sync_master_timeout       | 10000 | #设置超时时间
| rpl_semi_sync_master_trace_level   | 32    | # 设置追踪级别
| rpl_semi_sync_master_wait_no_slave | ON    | # 没有从节点是否等待
+------------------------------------+-------+
5 rows in set (0.07 sec)

mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.05 sec)

mysql> set global rpl_semi_sync_master_timeout=1000;
Query OK, 0 rows affected (0.00 sec)

从服务器上操作

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.09 sec)

mysql> show global variables like '%rpl%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_recovery_rank               | 0     |
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
3 rows in set (0.00 sec)

mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)

在主服务器上查询当前的数据库的状态

mysql> show global status like '%%rpl%';
+--------------------------------------------+-------------+
| Variable_name                              | Value       |
+--------------------------------------------+-------------+
| Rpl_semi_sync_master_clients               | 0           |
| Rpl_semi_sync_master_net_avg_wait_time     | 0           |
| Rpl_semi_sync_master_net_wait_time         | 0           |
| Rpl_semi_sync_master_net_waits             | 0           |
| Rpl_semi_sync_master_no_times              | 0           |
| Rpl_semi_sync_master_no_tx                 | 0           |
| Rpl_semi_sync_master_status                | ON          |
| Rpl_semi_sync_master_timefunc_failures     | 0           |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0           |
| Rpl_semi_sync_master_tx_wait_time          | 0           |
| Rpl_semi_sync_master_tx_waits              | 0           |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0           |
| Rpl_semi_sync_master_wait_sessions         | 0           |
| Rpl_semi_sync_master_yes_tx                | 0           |
| Rpl_status                                 | AUTH_MASTER |
+--------------------------------------------+-------------+
15 rows in set (0.01 sec)

从服务器上重新启动IO进程

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

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

测试

测试一:在主服务器上创建表
mysql> create table tb1 (id int);
Query OK, 0 rows affected (0.23 sec)
测试二: 停止从服务器上的IO进程

停止从服务器上的IO进程

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

在主服务器上创建一个表

mysql> create table tb4 (id int);
Query OK, 0 rows affected (1.08 sec)

总结:使用半同步复制,如果从服务器挂掉,主服务器会等待从服务器超过预先设置的超时时间。

mysql> create table tb5 (id int);
Query OK, 0 rows affected (0.06 sec)

总结:如果半同步复制失败,会自动切换到异步复制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MySQL主从同步是一种数据复制机制,用于将一个MySQL数据库实例中的数据自动复制到其他MySQL数据库实例,从而实现数据的备份、负载均衡和故障恢复等功能。 在主从同步中,一个MySQL实例被配置为主服务器(Master),而其他实例被配置为从服务器(Slave)。主服务器负责接收和处理客户端的写操作,然后将这些操作记录到二进制日志(Binary Log)。从服务器连接到主服务器,并通过读取主服务器的二进制日志来复制这些操作。从服务器将这些操作应用到自己的数据上,以保持与主服务器数据的一致性。 配置MySQL主从同步需要进行以下步骤: 1. 确保主服务器和从服务器之间可以互相通信。 2. 在主服务器上开启二进制日志功能,并配置二进制日志文件的位置和名称。 3. 在主服务器上创建一个用于复制的用户,并为该用户授予复制权限。 4. 在从服务器上配置复制参数,包括指定主服务器的IP地址、连接用户名和密码等。 5. 启动从服务器,并连接到主服务器进行复制。 6. 监控主从同步过程,确保数据的一致性和同步性。 需要注意的是,在配置主从同步时,需要考虑网络延迟、带宽和硬件性能等因素,以确保同步过程的效率和稳定性。另外,主从同步只能复制数据更改操作(如插入、更新、删除),而不能复制结构变更操作(如创建表、修改表结构)。如果需要同步结构变更,可以使用其他工具或方法来实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值