mysql主从复制原理

一、mysql复制解决的问题

  1. 实现在不同服务器上的数据分布
  2. 实现数据读取的负载均衡
  3. 增强数据安全性,利用备库的备份来减少主库的负载,方便进行数据库高可用的架构部署

      避免MySQL单点失败

     4、实现数据库的在线升级

二、MySQL二进制日志

二进制日志记录了所有对MySQL数据库的修改事件,包括增删改查事件与对表结构的修改事件

二进制日志的记录格式:

1.基于段的格式binlog_format=STATEMENT

优点:日志记录量相对较小,节约磁盘及网络I/O,只对一条记录修改或者插入

row 格式所产生的日志量小于段产生的日志量

缺点:必须要记录上下文信息,保证语句在从服务器上执行结果与住服务器上相同

特定的函数如UUID(),user() 这样非确定性函数还是无法复制,可能造成MySQL复制的主

备服务器的数据不一致

查看binlog日志格式

登录数据库

[root@localhost ~]# mysql -uroot -p

Enter password:

mysql> show variables like 'binlog_format';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| binlog_format | MIXED |

+---------------+-------+

1 row in set (0.00 sec)

临时更改日志格式

set session binlog_format=statement;

在 /etc/my.cnf文件中也可以修改,修改之后需要重启mysql服务

刷新binlog

mysql> show binary logs;

+------------------+-----------+

| Log_name | File_size |

+------------------+-----------+

| mysql-bin.000001 | 177 |

| mysql-bin.000002 | 177 |

| mysql-bin.000003 | 437 |

| mysql-bin.000004 | 1403 |

| mysql-bin.000005 | 177 |

| mysql-bin.000006 | 201 |

| mysql-bin.000007 | 201 |

| mysql-bin.000008 | 177 |

| mysql-bin.000009 | 154 |

+------------------+-----------+

9 rows in set (0.00 sec)

 

mysql>

mysql> flush logs;

Query OK, 0 rows affected (0.02 sec)

mysql> show binary logs;

+------------------+-----------+

| Log_name | File_size |

+------------------+-----------+

| mysql-bin.000001 | 177 |

| mysql-bin.000002 | 177 |

| mysql-bin.000003 | 437 |

| mysql-bin.000004 | 1403 |

| mysql-bin.000005 | 177 |

| mysql-bin.000006 | 201 |

| mysql-bin.000007 | 201 |

| mysql-bin.000008 | 177 |

| mysql-bin.000009 | 201 |

| mysql-bin.000010 | 154 |

+------------------+-----------+

10 rows in set (0.00 sec)

插入测试数据

mysql> create table t(id int,c1 varchar(10));

Query OK, 0 rows affected (0.03 sec)

mysql> insert into t values(1,'22'),(2,'rrr');

Query OK, 2 rows affected (0.00 sec)

Records: 2 Duplicates: 0 Warnings: 0

用mysqlbin查看日志文件

/usr/local/mysql/bin/mysqlbinlog mysql-bin.000010

可以看到执行的sql语句

2、基于行的日志格式,binlog_format=ROW

可以避免MySQL主从复制中主从不一致的问题,同一个sql语句修改1000条数据的情况下,基于段的日志格式只会记录这个sql语句,基于行的日志会有1000条记录分别记录每一行数据的修改

优点:

1、mysql主从复制更加安全

2、对每一行数据修改比基于段的高效

基于行的日志格式可以对数据进行恢复

缺点:1、日志记录量非常大

 

日志量控制参数

binlog_row_image=[FULL|MINIMAL|NOBLOB]

FULL记录每一行的变更,minimal只记录影响后的行

修改binlog日志格式

mysql> set session binlog_format=ROW;

刷新日志

mysql> flush logs;

查看参数binlog_row_image

mysql> show variables like 'binlog_row_image';

+------------------+-------+

| Variable_name | Value |

+------------------+-------+

| binlog_row_image | FULL |

+------------------+-------+

1 row in set (0.00 sec)

增加一列

mysql> alter table t add c2 text;

mysql> insert into t values(3,'ee','ttt');

mysql> delete from t where id=1;

update t set c2='ttwwwtt' where id=2;

 

/usr/local/mysql/bin/mysqlbinlog -vv mysql-bin.000011

查看日志

更新记录了每列的变化前后的值

mysql主从复制原理_第1张图片

可以看到日志记录的删除的详细信息

mysql主从复制原理_第2张图片

设置

mysql> set session binlog_row_image=minimal;

mysql> update t set c2='tttt' where id=2;

/usr/local/mysql/bin/mysqlbinlog -vv mysql-bin.000011

可以看到修改前后的值

mysql主从复制原理_第3张图片

但是没有记录其他列的变化值

修改参数

set session binlog_row_image=noblob;

该参数更新text列不被记录

mysql> update set c1='tttsss' where id=3;

mysql主从复制原理_第4张图片

查看日志没有记录text列的更新前后的值

3.混合日志格式binlog_format=MIXED

特点:根据SQL语句由系统决定是在基于段与基于行的日志格式中进行决策,数据量的大小由执行的sql语句决定

 

基于行的日志对复制的影响

优点:可以应用于任何sql的复制包括非确定性函数,存储过程

可以减少数据库锁的使用

缺点:要求主要从数据库的表结构相同,否则可能会中断复制

无法在从上单独执行触发器

 

 

三、MySQL主从复制工作方式

mysql主从复制原理_第5张图片

 

 

1、主将变更写入二进制日志

2、从读取主的二进制日志变更到relay_log中

3、在从上重放relay_log中的日志

基于sql段的日志是在从库上重新执行记录的sql

基于行的日志则是在从库上直接应用对数据库行的修改

二、配置MySQL复制

1、基于日志点的复制配置步骤

在主DB服务器上建立复制账号

create user 'repl' @ 'IP段', identified by 'PassWord';建立账户

grant replication slave on *.* to 'repl' @ 'IP段' 账户授权

配置主数据库服务器:

bin_log=mysql-bin

server_id=1 //server_id 在集群中唯一

配置从服务器

bin_log=mysql-bin

server_id=2

relay_log=mysql-relay-bin

log_slave_update=on (可选,设置中继服务器必须设置on)

read_only=on(可选)

初始化从服务器数据

mysqldump --master-data=2 --single-transaction

xtrabackup --slave -info (可用于热备份)

启动复制链路

change master to matser_host = 'master_host_ip',

master_user='repl',

master_password = 'PassWord',

master_log_file = 'mysql_log_file_name',//主上的二进制文件

matser_log_pos=4//复制偏移量

配置机器,主数据库ip192.168.31.101,从数据库192.168.31.102

在主数据库上创建账户并授权

mysql> create user repl@'192.168.31.%' identified by '123456';

grant replication slave on *.* to repl@'192.168.31.%';

flush privileges;

更改主从数据库配置

server-id = 1(从数据库设置为2)

log-bin=mysql-bin

binlog_format=row

对主数据库进行备份

[root@localhost ~]# /usr/local/mysql/bin/mysqldump --single-transaction --master-data --triggers --routines --all-databases -uroot -p >>all.sql

将备份sql拷贝到从数据库

在从库上导入sql

mysql -uroot -p

在从库上设置复制链路

mysql> change master to master_host='192.168.31.101',

-> master_user='repl',

-> master_password='123456',

-> MASTER_LOG_FILE='mysql-bin.000014', MASTER_LOG_POS=154;

Query OK, 0 rows affected, 2 warnings (0.01 sec)

在备份的sql文件中可以看到二进制文件与偏移量

mysql主从复制原理_第6张图片

复制链路配置完查看信息

mysql> show slave status\G;

*************************** 1. row ***************************

Slave_IO_State:

Master_Host: 192.168.31.101

Master_User: repl

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000014

Read_Master_Log_Pos: 154

Relay_Log_File: localhost-relay-bin.000001

Relay_Log_Pos: 4

Relay_Master_Log_File: mysql-bin.000014

Slave_IO_Running: No

Slave_SQL_Running: No

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: 154

Relay_Log_Space: 154

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

Master_UUID:

Master_Info_File: /usr/local/mysql/var/master.info

SQL_Delay: 0

SQL_Remaining_Delay: NULL

Slave_SQL_Running_State:

Master_Retry_Count: 86400

Master_Bind:

Last_IO_Error_Timestamp:

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:

在从数据库上执行start slave;开始主从复制

基于日志点的优点:

1、 mysql最早支持的复制技术,Bug相对较少对

2、对sql执行没有任何限制

3、故障处理容易

基于日志点的缺点:

1、故障转移时重新获取新的日志点信息比较困难

 

2、基于GTID的复制

GITD(Global Transaction Identifiers)即全局事务ID,其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID

在主DB上建立复制账户

create user 'repl' @ 'ip段' identified by 'PassWord';

grant replication slave on *.* to 'repl' @ 'ip段';

配置主数据库

log-bin=mysql-bin

server_id=1

gtid_mode=on

enforce_gtid_consistency 强制GTIP一致性

log-slave-updates=on(5.7中不用设置)

从数据库配置

relay_log=/usr/local/mysql/log/relay_log

gtid_mode=on

enforce_gtid_consistency

read_only=on 建议保证从库数据不被修改

master_info_repository=table 建议

relaiy_log_info_repository = table 建议

 

初始化从服务器与基于点的主从复制一样

启动基于GTID的复制

change master to master_host = 'matser_host_ip',

matser_user = 'repl',

matser_password='PassWord',

matser_auto_position=1

 

在主服务器与从服务器配置文件中加入上述配置项

备份数据

mysqldump --single-transaction --master-data=2 --triggers --routines --all-databases -uroot -p >>all2.sql

在备份文件中可以看到gtid事务初始位置

mysql主从复制原理_第7张图片

在从数据库上进行数据恢复,配置复制链路

mysql -uroot -p

change master to master_host='192.168.31.101',master_user='repl',master_password='123456',master_auto_position=1;

start slave;

GTID优点

1、可以方便的进行故障转移

2、从库上不会丢失主库上的任何修改

缺点:

1、故障处理比较复杂

2、对执行的sql有一定限制(不能用create table select 建表)

 

 

 

你可能感兴趣的:(mysql)