zoukankan      html  css  js  c++  java
  • 浅析MySQL复制

    MySQL的复制是基于binlog来实现的。

    流程如下

    涉及到三个线程,主库的DUMP线程,从库的IO线程和SQL线程。

    1. 主库将所有操作都记录到binlog中。当复制开启时,主库的DUMP线程根据从库IO线程的请求将binlog中的内容发送到从库。

    2. 从库的IO线程接受到主库DUMP线程发送的binlog事件后,将其写到本地的relay-log。

    3. 从库的SQL线程重放relay-log中的事件。

    实际上,在MySQL 4.0之前,复制只有两个线程,master和slave端各一个。在Slave端,该线程同时负责接收主库发来的binlog事件,也负责事件的重放,所以没有使用relay-log,这样容易导致,当binlog事件的重放速度较慢时,会影响binlog事件的接受。

    复制的搭建

    基本步骤如下:

    1. 配置主库和从库

    2. 创建复制的账号

    3. 创建主库一致性快照

    4. 根据主库的快照,建立从库

    5. 开启复制

    详细步骤如下

    1. 配置主库和从库

    主库

    开启binlog并设置server-id

    [mysqld]
    log-bin=mysql-bin
    server-id=1

    在一组复制结构中,每个服务器必须配置一个唯一的server-id。该值的有效范围为1~232-1。

    如果server-id设置为0的话,则MySQL会自动将它更改为1。此时,对复制没有影响。

    如果server-id没有显式设置的话,则MySQL同样会将它设置为1,但是从连接的时候,IO线程会报错

    Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Misconfigured master - server_id was not set'

    从库

    设置server-id

    [mysqld]
    server-id=2

    在从服务器上,可以选择不开启binlog。当开启了binlog后,如果想把重放的时间同样也记录到binlog中,可将log_slave_updates参数设置为1。

    设置完毕后,重启数据库

    2. 创建复制账号

    主库上执行

    mysql> CREATE USER 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
    mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.mydomain.com';

    3. 创建主库一致性快照

    在这里,我用mysqldump来创建数据库快照

    # mysqldump --master-data=2  -R --single-transaction -A > 3306_20160815.sql

    在生成的备份文件中,我们可以得到在对数据库执行一致性快照时主的状态,包括二进制文件的名称及位置

    # head -30 3306_20160815.sql

    ...
    -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000016', MASTER_LOG_POS=120;
    ...

    4. 根据主库的快照,建立从库

    # mysql < 3306_20160815.sql

    5. 开启复制

    根据第3步获取到的主库状态执行CHANGE MASTER TO命令

    mysql> CHANGE MASTER TO
             MASTER_HOST='master_host_name',
             MASTER_USER='replication_user_name',
             MASTER_PASSWORD='replication_password',
             MASTER_LOG_FILE='recorded_log_file_name',
             MASTER_LOG_POS=recorded_log_position;

    在执行CHANGE MASTER TO命令后,从库并不会连接到主库,而只是将这些信息写入到从库数据目录下的master.info和relay-log.info中。如果没有显式指定MASTER_LOG_FILE,则默认为空,因为此时还没有和主库建立连接,并不知道主库binlog的文件名称,只有等到和主库建立连接时才能知道。如果MASTER_LOG_POS没有显式指定,则默认为4,即忽略binlog的头4个字节,从第一个事件开始读取。

    开启复制功能

    mysql> start slave;

    查看复制的状态

    mysql> show slave statusG

    重点关注以下两个变量,如果为YES,则代表复制搭建成功。

    ...
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    ...

    注:以上搭建场景是基于主库上已经有一定的数据。如果在全新的环境中搭建,实际上会更简单。

    只需获取主库的状态信息即可

    mysql> show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000016 |      120 |              |                  |                   |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec

    MySQL复制的格式

    MySQL的复制有三种格式:

    Statement-based replication(SBR)

    基于语句的复制,即master上执行的SQL语句原封不动的在slave上重放。该复制格式在MySQL 3.23即出现了。

    优点:

    1. 节省binlog的空间。

    2. 可用于审核,毕竟所有的DML语句都是直接记录在binlog中。

    缺点:

    1. 很多函数在主从上执行的结果并不一致

    LOAD_FILE(),UUID(), UUID_SHORT(),USER(),FOUND_ROWS(),SYSDATE(),GET_LOCK(),IS_FREE_LOCK(),IS_USED_LOCK(),MASTER_POS_WAIT(),RAND(),RELEASE_LOCK(),SLEEP(),VERSION()

    2. DELETE和UPDATE操作,带了LIMIT子句,却没有带ORDER BY,可能导致主从执行的结果并不一致。

    3. 相对于基于行的复制,master上执行INSERT ... SELECT操作需要更多的行锁。

    4. 自定义函数(UDF)必须确保执行的结果是确定的。

    Row-based replication(RBR)

    基于行的复制,MySQL 5.1引入的,相对于SBR,它记录的是DML操作涉及到的行。

    优点:

    1. 安全。master上所有的变更都能复制到slave上。

    2. 在执行以下操作时,只需更少的行锁。

        INSERT ... SELECT

        带有AUTO_INCREMENT列的INSERT操作

        UPDATE和DELETE中,WHERE条件没有用上索引。

    缺点:

    1. 会产生大量的日志。

    譬如一张表有1w条记录,如果我不带任何条件执行delete操作,则在基于statement的复制中,在binlog中只会记录delete from table这一条记录,但是在基于row的复制中,则会记录1w笔记录,每笔记录类似于delete from table where ..。

    这会带来以下问题

     1> 如果利用binlog进行恢复,会需要更长的时间.

     2> 在写数据到binlog中时,因为数据量大,会导致binlog的锁定时间较长,影响数据库的并发。

     3> 较大的日志会对磁盘IO和网络IO产生较大的压力。

     4> 增大slave的延迟。

    2. 不会对二进制日志进行校验。

    3. 不推荐基于库级别的复制

        包括--replicate-do-db, --replicate-ignore-db, --replicate-rewrite-db

    MIXED

    MIXED是上述两者的的结合,会根据执行的语句和涉及的存储引擎自动在这两种模式间切换。默认情况下,采用的是基于语句的复制模式,在遇到unsafe statements时,会切换为基于行的复制模式。

    关于切换的条件,可参考官方文档:http://dev.mysql.com/doc/refman/5.7/en/binary-log-mixed.html

    在MySQL 5.7.7之前,默认的是基于语句的复制模式,从MySQL 5.7.7开始,默认基于行的复制模式。

    复制中涉及的文件

    relay-log

    relay-log保存着从库IO线程从主库读取到的binlog事件。和binlog格式一样,可通过mysqlbinlog解析其中的内容。

    可通过配置relay_log和relay_log_index参数设置relay-log和relay-log.index文件的名称。

    relay-log在如下情况下会发生切换:

    1. slave IO线程启动的时候。

    2. 执行FLUSH LOGS操作的时候。

    3. 达到参数max_relay_log_size设置的大小,默认为0,即以max_binlog_size的值作为max_relay_log_size的大小。

    slave SQL线程在重放完一个relay-log文件中的所有事件后,会自动删除relay-log文件(由relay_log_purge参数控制),所以没有显式删除relay-log的命令。

    master.info

    该文件保存了主库的主机名,端口,复制账号的用户名和密码,以及从库接受主库binlog事件的位置信息,通过这些位置信息,从库的IO线程知道下次从哪里获取主库的binlog事件。

    该位置信息对应于show slave statusG中的Master_Log_File和Read_Master_Log_Pos。

    如下所示:

    # cat master.info

    23
    mysql-bin.000014
    120
    192.168.244.10
    repl
    repl
    3306
    60
    0
    
    
    
    
    
    0
    1800.000
    
    0
    cad449f2-5d4f-11e6-b353-000c29c64704
    86400
    
    
    0

    relay-log.info

    该文件记录从库的重放信息,这样即便数据库发生重启,SQL线程也知道该从哪里开始重放。

    该位置信息对应于show slave statusG中的Relay_Master_Log_File和Exec_Master_Log_Pos。

    # cat relay-log.info

    7
    ./mysqld-relay-bin.000024
    283
    mysql-bin.000014
    120
    0
    0
    1
    1

    Crash-Safe Replication

    slave每次接受binlog或者应用relay-log时,都要修改master.info或relay-log.info的信息并同步到磁盘中,这会导致大量的磁盘操作,所以,一般都是采用异步方式来对这两个文件进行更改。虽然每次都会修改这些文件,但是持久化到磁盘却留给操作系统处理。在内存与磁盘中的信息不一致时,如果此时操作系统宕机,内存中的信息将无法及时同步到磁盘中。操作系统恢复后,master.info和relay-log.info的数据依然是旧的,所以会从已经执行的部分重新执行。

    MySQL 5.6为了改善这个问题,提供了两个参数,可将master.info和relay-log.info中的内容保存在表中而不是磁盘文件中。

    master-info-repository

    可设置为TABLE或FILE,如果使用FILE,则复制的位置信息依旧保存在master.info中,如果设置为TABLE,则信息报保存在mysql.slave_master_info中,默认为FILE。

    relay-log-info-repository

    可设置为TABLE或FILE,如果使用FILE,则应用relay-log的信息会保存在relay-log.info中,如果设置为TABLE,则保存在mysql.slave_relay_log_info中,默认为FILE。

    通过将上述两个变量设置为TABLE,可实现“Crash-Safe Replication”,上述的相关操作都会放到一个事务中进行。

    总结

    1. 启用复制功能并不会增加服务器太多的开销,主要是开启binlog带来的开销,包括binlog文件的追加写操作开销,以及系统调用fsync带来的开销。

    2. MySQL的复制功能具有向后兼容性,因为较新版本的MySQL的binlog中会进入新的事件类型。所以,可以将较新版本的MySQL作为从库。

    3. MySQL复制是异步的。

    4. MySQL 5.6开始新增延迟复制功能,由master_delay参数来控制。

    参考

    1. http://dev.mysql.com/doc/refman/5.7/en/replication-configuration.html

    2. MariaDB原理与实现

        

        

  • 相关阅读:
    Maximum Flow Exhaustion of Paths Algorithm
    ubuntu下安装java环境
    visualbox使用(二)
    vxworks一个超级奇怪的错误(parse error before `char')
    February 4th, 2018 Week 6th Sunday
    February 3rd, 2018 Week 5th Saturday
    February 2nd, 2018 Week 5th Friday
    February 1st, 2018 Week 5th Thursday
    January 31st, 2018 Week 05th Wednesday
    January 30th, 2018 Week 05th Tuesday
  • 原文地址:https://www.cnblogs.com/ivictor/p/5764978.html
Copyright © 2011-2022 走看看