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 STATUS\G
#主库有关的信息(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 status\G
*************************** 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  status\G
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

  

  

  

  

  

  

  

 

posted @ 2018-10-18 16:22  ForLivetoLearn  阅读(217)  评论(0编辑  收藏  举报