zoukankan      html  css  js  c++  java
  • mysql主从复制

    • 主从复制原理
    1.从库执行change master to 命令(主库的连接信息+复制的起点)
    2.从库会将以上信息,记录到master.info文件
    3.从库执行 start slave 命令,立即开启IO_T和SQL_T
    4. 从库 IO_T,读取master.info文件中的信息,获取到IP,PORT,User,Pass,binlog的位置信息
    5. 从库IO_T请求连接主库,主库专门提供一个DUMP_T,负责和IO_T交互
    6. IO_T根据binlog的位置信息(mysql-bin.000004 , 444),请求主库新的binlog
    7. 主库通过DUMP_T将最新的binlog,通过网络TP给从库的IO_T
    8. IO_T接收到新的binlog日志,存储到TCP/IP缓存,立即返回ACK给主库,并更新master.info
    9.IO_T将TCP/IP缓存中数据,转储到磁盘relaylog中.
    10. SQL_T读取relay.info中的信息,获取到上次已经应用过的relaylog的位置信息
    11. SQL_T会按照上次的位置点回放最新的relaylog,再次更新relay.info信息
    12. 从库会自动purge应用过relay进行定期清理
    补充说明:
    一旦主从复制构建成功,主库当中发生了新的变化,都会通过dump_T发送信号给IO_T,增强了主从复制的实时性.
    • 搭建主从复制

    1.编辑主库配置文件,添加如下内容

    [root@localhost pub]# vi /etc/my.cnf
    [mysqld]
    log_bin=master-bin        #开启二进制日志,并给二进制日志文件起名
    server_id=1                     #配置服务器节点id,全局唯一
    innodb_file_per_table=ON      #开启每表单独存储
    skip_name_resolve=on           #关闭域名反解 

    2.查看二进制日志开启情况

    MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%log_bin%';
    +---------------------------------+-------+
    | Variable_name                   | Value |
    +---------------------------------+-------+
    | log_bin                         | ON    |
    | log_bin_trust_function_creators | OFF   |
    | sql_log_bin                     | ON    |
    +---------------------------------+-------+
    3 rows in set (0.00 sec)
    
    MariaDB [(none)]> SHOW MASTER LOGS;
    +-------------------+-----------+
    | Log_name          | File_size |
    +-------------------+-----------+
    | master-bin.000001 |     30379 |
    | master-bin.000002 |   1038814 |
    | master-bin.000003 |       245 |
    +-------------------+-----------+
    3 rows in set (0.00 sec)
    

     3.查看服务id

    MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%server_id';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | server_id     | 1     |
    +---------------+-------+
    1 row in set (0.00 sec)
    

    4.创建一个拥有复制权限的账号,并将主库锁定,不能写入 

    MariaDB [mysql]> GRANT REPLICATION SLAVE , REPLICATION CLIENT ON *.* TO copy@'%' IDENTIFIED BY 'copy';
    MariaDB [mysql]> FLUSH PRIVILEGES ;
    MariaDB [mysql]> FLUSH tables with read lock; 

    4.1在主库中备份出所有数据,在从库上恢复

    #主库备份
    [root@localhost ~]# mysqldump -uroot -p 数据库名称 > /root/备份库位置
    Enter password: 
    
    
    #从库恢复
    [root@localhost ~]# mysql -uroot -p 数据库名称 < 数据库备份文件
    Enter password: 

    5.编辑从库配置文件

    [root@back ~]# vi /etc/my.cnf
    relay_log=relay-log         #开启中继日志
    server_id=2                      #配置服务器节点id,全局唯一
    innodb_file_per_table=ON          #开启每表单存储
    skip_name_resolve=ON             #关闭域名反解
    

    6.查看中继日志是否开启

    MariaDB [mysql]> SHOW GLOBAL VARIABLES LIKE '%relay_log';
    +----------------------------------+-----------+
    | Variable_name                    | Value     |
    +----------------------------------+-----------+
    | innodb_recovery_update_relay_log | OFF       |
    | relay_log                        | relay-log |
    | sync_relay_log                   | 0         |
    +----------------------------------+-----------+
    3 rows in set (0.00 sec)
    

    7.查看server_id

    MariaDB [mysql]> SHOW GLOBAL VARIABLES LIKE '%server_id%';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | server_id     | 2     |
    +---------------+-------+
    1 row in set (0.00 sec)
    

    8.设置主库位置及其他信息

    MariaDB [hellodb]> CHANGE MASTER TO 
        -> MASTER_HOST='172.17.148.255' ,     #主库地址
        -> MASTER_USER='copy' ,                      #复制用户
        -> MASTER_PASSWORD='copy' ,           #用户密码
        -> MASTER_LOG_FILE='master-bin.000003' ,     #从哪个二进制文件开始复制
        -> MASTER_LOG_POS=245;                   #复制起始位置
    

    9.开启复制线程

    MariaDB [mysql]> START SLAVE ;

    10.查看SLAVE状态

    MariaDB [mysql]> SHOW SLAVE STATUS G
    

     11.主库解锁

    MariaDB [mysql]> UNLOCK TABLES;
    

    复制架构中应该注意的问题

    • 1.限制从服务器为只读 

      在从服务器上限制read_only=ON,此限制对拥有super权限的用户均无效(mysql可以开启super_read_only限制super用户)

    MariaDB [hellodb]> SET GLOBAL read_only=ON;
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [hellodb]> SHOW GLOBAL VARIABLES LIKE 'read_only';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | read_only     | ON    |
    +---------------+-------+
    1 row in set (0.00 sec)  

      或是在配置文件中添加此项

    [root@back ~]# vi /etc/my.cnf
    read_only=ON
    
    • 2.如何保证主从复制的事务安全

      在master节点启用参数

    sync_binlog=ON   #事务提交时,立即将内存中的二进制文件写入磁盘
    sync_master_info=ON     #马上同步这个文件内容至磁盘
    innodb_flush_logs_at_trx_commit=ON   #提交时,立即将日志写入磁盘
    innodb_support_xa=ON     #支持分布式  

      在slave节点启用参数

    skip_slave_start=ON       #关闭自动提交
    sync_relay_log=ON          #文件立即同步至磁盘
    sync_relay_log_info=ON    #立即同步至磁盘
    • 3.延时复制:防止主库删除重要数据后,从库马上同步。
    #原理:IO线程将数据写入relaylog中,SQL线程"慢点"运行;一般企业建议3-6小时,具体看公司运维人员对于故障的反应时间
    
    mysql>stop slave;
    mysql>CHANGE MASTER TO MASTER_DELAY = 300;
    mysql>start slave;
    mysql> show slave status G
    SQL_Delay: 300
    SQL_Remaining_Delay: NULL
    
    #排查思路
    延时从库处理逻辑故障
    1.2.1 延时从库的恢复思路
    (1) 监控到数据库逻辑故障
    (2) 停从库SQL线程,记录已经回放的位置点(截取日志起点)
    (3) 截取relaylog,
      起点: show slave status G Relay_Log_File ,Relay_Log_Pos
      终点: drop之前的位置点:show relaylog events in ''	
    (4) 模拟SQL线程回放日志
    (5) 恢复业务
    	情况一: 就一个库的话
    	从库替代主库工作
    	情况二: 
    	从库导出故障库,还原到主库中.
    
    #故障演练
    主库 : 
    create database delay charset utf8mb4;
    use delay;
    create table t1 (id int);
    insert into t1 values(1),(2),(3);
    commit;
    drop database delay;
    
    从库:
    
    # 1.停止 从库SQL 线程,获取relay的位置点
    mysql> stop slave sql_thread;
    mysql> show slave status G
    Relay_Log_File: db01-relay-bin.000002
    Relay_Log_Pos: 626
    
    # 2. 找到relay的截取终点
    mysql> show relaylog events in 'db01-relay-bin.000002';
    | db01-relay-bin.000002 | 1299 | Query          |         7 |        1228 | drop database delay            
    
    3. 截取relay
    [root@db01 data]# cd /data/3308/data/
    [root@db01 data]# mysqlbinlog --start-position=626 --stop-position=1299 db01-relay-bin.000002 >/tmp/relay.sql
    
    4. 恢复relay到从库
    [root@db01 data]# mysql -uroot -p -S /data/3308/mysql.sock 
    mysql> set sql_log_bin=0;
    mysql> source /tmp/relay.sql
    
    • 4.过滤复制
    #选择指定的数据库进行复制,减轻主库压力
    #replicate_do_db:要复制的库
    #replicate_ignore_db:不复制的库,只需要开启一项配置就行
    #过滤复制应用:从库配置文件,加上要复制的库名
    vim /etc/my.cnf
    replicate_do_db=wordpress
    [root@db01 data]# systemctl restart mysqld
    
    #查看从库复制状态
    mysql> show slave status G
    Replicate_Do_DB: wordpress
    Replicate_Ignore_DB:

    *如果从库之前做过复制,需要清空之前的配置

    #先停止复制
    mysql> stop slave;
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    
    #再清空状态
    mysql> reset slave;
    Query OK, 0 rows affected (0.00 sec)
    
    #重新配置
    mysql> CHANGE MASTER TO 
        -> MASTER_HOST='10.69.39.73',
        -> MASTER_USER='copy',
        -> MASTER_PASSWORD='copy',
        -> MASTER_LOG_FILE='mysql-bin.000002',
        -> MASTER_LOG_POS=106;
    Query OK, 0 rows affected (0.01 sec)
    
    #开启复制
    mysql> start slave;
    Query OK, 0 rows affected (0.00 sec)
    

      

    *查看主从状态

    #主库的Position不能为0
    mysql> SHOW MASTER STATUS G
    *************************** 1. row ***************************
                File: mysql-bin.000002
            Position: 106
        Binlog_Do_DB: gz_namc
    Binlog_Ignore_DB: mysql
    1 row in set (0.00 sec)
    
    
    #从库的Slave_IO_Running,Slave_SQL_Running要为yes
    
    mysql> SHOW SLAVE STATUSG
    #主库有关的信息(master.info):
    Master_Host: 10.0.0.51
    Master_User: repl
    Master_Port: 3307
    Connect_Retry: 10
    *******************************
    Master_Log_File: mysql-bin.000004
    Read_Master_Log_Pos: 609
    *******************************
    
    #从库relay应用信息有关的(relay.info):
    Relay_Log_File: db01-relay-bin.000002
    Relay_Log_Pos: 320
    Relay_Master_Log_File: mysql-bin.000004
    
    #从库线程运行状态(排错)
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Last_IO_Errno: 0
    Last_IO_Error: 
    Last_SQL_Errno: 0
    Last_SQL_Error: 			
    			
    #过滤复制有关的信息:			
    Replicate_Do_DB: 
    Replicate_Ignore_DB: 
    Replicate_Do_Table: 
    Replicate_Ignore_Table: 
    Replicate_Wild_Do_Table: 
    Replicate_Wild_Ignore_Table: 
     
    #从库延时主库的时间(秒):  
    Seconds_Behind_Master: 0
    				
    #延时从库:
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    
    #GTID复制有关的状态信息		  
    Retrieved_Gtid_Set: 
    Executed_Gtid_Set: 
    Auto_Position: 0
    

     

    *自动删除之前的二进制日志

    #设置最多保留多长时间之前的日志
    mysql> set GLOBAL expire_logs_days=30;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SHOW VARIABLES LIKE 'expire_logs_days';
    +------------------+-------+
    | Variable_name    | Value |
    +------------------+-------+
    | expire_logs_days | 30    |
    +------------------+-------+
    1 row in set (0.00 sec)
    

      

    slave复制停了很久,重新倒库,重新reset slave出现relay log报错的解决办法

    处理一则MySQL Slave环境出现ERROR 1201 (HY000): Could not initialize master info structure的案例。
    
    冷备份方式复制一份新的slave,初始化参数中已经修改了相关文件路径及server_id等关联参数。
    但在启动slave时发现error_log中出现下列错误信息:
    120326 11:10:23 [ERROR] /usr/local/mysql//libexec/mysqld: File '/data/mysqldata/3306/binlog/mysql-relay-bin.000002' not found (Errcode: 2)
    120326 11:10:23 [ERROR] Failed to open log (file '/data/mysqldata/3306/binlog/mysql-relay-bin.000002', errno 2)
    120326 11:10:23 [ERROR] Failed to open the relay log '/data/mysqldata/3306/binlog/mysql-relay-bin.000002' (relay_log_pos 126074557)
    120326 11:10:23 [ERROR] Could not open log file
    120326 11:10:23 [ERROR] Failed to initialize the master info structure
    
    由于新的slave改变了服务端口和文件路径,分析应该是由于mysql-relay-bin.index中仍然保存着旧relay日志文件的路径,而这些路径下又找不到合适的文件,因此报错。
    
    对于这类问题解决起来是比较简单的,重置slave的参照即可,执行命令如下:
    mysql> reset slave;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> change master to 
        -> master_host='10.0.0.101',
        -> master_port=3306,
        -> master_user='repl',
        -> master_password='repl',
        -> master_log_file='mysql-bin.000011',
        -> master_log_pos=1;
    ERROR 29 (HY000): File '/data/mysqldata/3306/binlog/mysql-relay-bin.000001' not found (Errcode: 2)
    看来应该还是mysql-relay-bin.index的问题,删除该文件及关联的relay-bin文件。再次配置master:
    mysql> change master to 
        -> master_host='10.0.0.101',
        -> master_port=3306,
        -> master_user='repl',
        -> master_password='repl',
        -> master_log_file='mysql-bin.000011',
        -> master_log_pos=1;
    ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log
    
    出现了新的错误,按照提示查看error_log也没发现更多错误信息,error_log中只是显示一条:
    120326 11:14:27 [ERROR] Error reading master configuration
    在操作系统端查看master/slave的配置文件,发现是两个0字节文件:
    -rw-rw---- 1 mysql mysql     0 Mar 26 11:13 master.info
    -rw-rw---- 1 mysql mysql     0 Mar 26 11:13 relay-log.info
    会不会是这个原因呢,直接删除这两个文件,然后尝试重新执行change master:
    
    mysql> change master to 
        -> master_host='10.0.0.101',
        -> master_port=3306,
        -> master_user='repl',
        -> master_password='repl',
        -> master_log_file='mysql-bin.000011',
        -> master_log_pos=1;
    Query OK, 0 rows affected (0.00 sec)
    
    成功,启动slave并查看状态:
    mysql> start slave;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> show slave statusG
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 10.0.0.101
                      Master_User: repl
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000011
              Read_Master_Log_Pos: 101
    ...........
    
    故障解决。
    

      

    主从延时监控及原因 

    5.6.1 主库方面原因
    (1) binlog写入不及时
    sync_binlog=1
    (2) 默认情况下dump_t 是串行传输binlog *****
    在并发事务量大时或者大事务,由于dump_t 是串型工作的,导致传送日志较慢
    如何解决问题?
    必须GTID,使用Group commit方式.可以支持DUMP_T并行
    (3) 主库极其繁忙
    慢语句
    锁等待
    从库个数
    网络延时
    5.6.2 从库方面原因
    (1) 传统复制(Classic)中 *****
    如果主库并发事务量很大,或者出现大事务
    由于从库是单SQL线程,导致,不管传的日志有多少,只能一次执行一个事务.
    5.6 版本,有了GTID,可以实现多SQL线程,但是只能基于不同库的事务进行并发回放.(database) 
    5.7 版本中,有了增强的GTID,增加了seq_no,增加了新型的并发SQL线程模式(logical_clock),MTS技术
    (2) 主从硬件差异太大
    (3) 主从的参数配置
    (4) 从库和主库的索引不一致
    (5) 版本有差异
    
    
    5.6.3 主从延时的监控
    
    show slave  statusG
    Seconds_Behind_Master: 0
    
    主库方面原因的监控
    
    主库:
    mysql> show master status ;
    File: mysql-bin.000001
    Position: 1373
    
    从库
    Master_Log_File: mysql-bin.000001
    Read_Master_Log_Pos: 1373
    
    从库方面原因监控:
    
    拿了多少:
    Master_Log_File: mysql-bin.000001
    Read_Master_Log_Pos: 691688
    执行了多少:
    Relay_Log_File: db01-relay-bin.000004
    Relay_Log_Pos: 690635
    Exec_Master_Log_Pos: 691000
    Relay_Log_Space: 690635
    

      

      

      

      

      

      

      

    初学linux,每学到一点东西就写一点,如有不对的地方,恳请包涵!
  • 相关阅读:
    软件工程第二次作业
    第一次作业
    理论物理特训-02
    左神-06 二叉树
    哲学通论之人-05(end)
    哲学通论之人-04
    左神-05 二分搜索(多看几遍)
    哲学通论之人-01
    航空母舰-04(end)
    题解 P3126 【[USACO15OPEN]回文的路径Palindromic Paths】
  • 原文地址:https://www.cnblogs.com/forlive/p/9811274.html
Copyright © 2011-2022 走看看