MySQL主从复制(详细过程以及从库不能同步的解决办法)

前面已经在本地搭建了多个MySQL的实例,可以用这些实例进行主从复制。

主要是三个线程,主库上的binlog dump线程、从库I/O线程、从库SQL线程

端口3306的MySQL实例作为主服务器(master),端口3307、3308的MySQL实例作为从服务器(slave)

基本过程为:

1.启动主库并配置可以复制的用户

2.启动从库(I/O线程),连接主库

3.当主库由相应操作时,保存二进制文件binlog,主库通过binlog dump线程发送给从库的I/O线程,I/O线程将binlog中的内容更新到relay log中去(注意:一个主库对应一个从库都会有一个binlog dump线程,如果有多个从库,则主库会存在多个binlog dump线程)

4.从库上的SQL线程读取relay log中的语句并执行。

5.从库执行完毕之后,删除relay log,以免relay log太多占用磁盘空间

补充:

如果从库宕机恢复之后,从库如何知道宕机之前在复制到哪了?

从库会默认创建两个文件保存复制的进度:master.info、relay-log.info

关于完整的MySQL主从复制文档,可参见官方文档,里面的步骤说的已经很详细了。

binlog可以有三种格式。设置为:

binlog_format=Statement  存储的是执行的SQL的语句,如 update user set user.created > '2020-01-01'

binlog_format=Row 存储的是具体的行数据。针对上面的语句可能,满足条件的数据有100行,则会把这100行数据详细记录在binlog中。当然此时,binlog文件的内容要比第一种多很多。

binlog_format=Mixed  包含以上两种

1.在master的配置文件中,在[mysqld]下开启log-bin功能,以及分配一个server-id(server-id官方文档给出的范围是1到2^{31}-1)

[mysqld]
server-id = 1
port=3306
socket=/tmp/mysql.sock1
key_buffer_size=16M
max_allowed_packet=8M
datadir=/usr/local/mysql3306/data
basedir=/usr/local/mysql3306
pid-file = /usr/local/mysql3306/data/3306.pid
#开启mysql的日志功能
log-bin = mysql-bin
innodb_flush_log_at_trx_commit=1
#每次事务提交,MySQL都会调用文件系统,将binlog刷新到磁盘上,默认为0,是不开启的,不建议开启,如果事务并发提交很多,高频率对磁盘的IO也会影响MySQL的性能
sync_binlog=0

登录master,查看log-bin是否已经开启(ON代表开启)

show variables like 'log_bin';

在master上创建专门用来复制的用户(repl-自定义的用户名,localhost-这里我填的是本地,如果slave不在你本机,可以填写slave的IP,12345是此用户的密码)

提示:如果是MySQL8的话,默认采用的是caching_sha2_password密码策略,除非你已经配置了SSL连接,否则,从数据库连接时依然连不上,如下图:

select user,host,plugin,authentication_string from user \G

可以将MySQL8的密码策略修改位mysql_native_password

create user 'repl'@'localhost' identified with 'mysql_native_password' by '12345';

授权

grant replication slave on *.* to 'repl'@'localhost';

重启master实例,查看用户是否创建成功,授权是否成功

select user,host from mysql.user;
show grants for 'repl'@'localhost';

如果授权成功,会是下面这样

授权成功查询结果

在slave的两个实例上配置server-id即可,每个实例的server-id要不同.

启动3307、3308两个实例,命令行进入slave实例,这里以3308实例举例子说明

1.进入3308实例,因为是一个机器多个实例,所以要指定socket,-S 是3308实例的socket的位置,可在my.cnf配置

 mysql -uroot -p -S /tmp/mysql.sock3

2.对从数据库进行相应的设置

change master to master_host='localhost',master_user='repl',master_password='12345',master_log_file='mysql-bin.000002',master_log_pos=2123;

 最后两个参数,master_log_file和master_pos不知道,怎么办?

在master实例上查看即可

show master status;

显示如下图:

查询结果

注意最后一个参数是不带 ' ',不要多写了

3.设置好之后,启动slave

start slave;

4.查看(注意,这个SQL结尾是没有 ;  如果加了 ; 会在最下面看到一个ERROR:No query specified的提示)

show processlist \G

显示信息

5.接下来则可以在主库上插入一条数据,测试从库是否同步过来了

在主库master插入一条数据之后,查看主库数据

use dhb(我的一个数据库);
insert into user (id,name,age) values (111,'测试slave',112);
select * from user;

在从库slave(3308)上查看

use dhb;
select * from user;

如果查到,则代表同步成功,如果发现从库没有更新刚才主库插入的那条数据怎么排查错误呢?

在从库slave上执行(注意:这里\G后面同样没有;)

show slave status \G

重点关注:Last_IO_Error(这里一般显示的具体错误信息)、Master_Log_File、Read_Master_Log_Pos这三项,后两项是是否和master实例保持一致

不能复制的错误图

可以看到,这里的Last_IO_Error,应该是我master_password密码错了(或者master没有启动SSL连接,具体解决方法在上面),修改slave的master_password即可,修改某一项的参数命令如下:

stop slave;
change master to master_password(修改哪一个参数就写哪一个,不需要修改的就不写)='12345';
start slave;

如果想要只复制特定的数据库、特定的数据表可以 在salve实例的my.cnf配置文件指定即可

replicate-ignore-table = dhb.user
replicate-ignore-db = otherdb
replicate-do-db = dhb
replicate-do-table = dhb.gener

主库master上所有的insert、update、delete操作以及新建表、修改表、删除表操作都会同步到从库slave上。

常见问题:

如果在从库上删除了一条记录,然后在主库上更新该条记录(update语句),从库会更新失败,

接着,在主库中新插入一条数据,发现从库并没有复制过来,如下图

报错信息

出现这个问题是因为:

如果从库止执行binlog中的SQL出错时(比如更新一条从库里没有的数据、或者主键冲突),这是从库会停止复制,不再进行同步,等待用户介入处理。

处理方法:使用该参数的从库不是主要当做主库的备份数据库,只是查询数据库分担压力而已,如果该slave被用来当做主库的备份数据库,强烈不建议此参数。

#可以使用下面的参数,直接跳过错误,继续执行,其中all代表所有参数,也可以配置一个数组[具体放的是err_code,err_code2,...]
slave-skip-errors = all

如果想要彻底结束主从复制关系,可以

1.在从数据库上执行
stop slave;
reset slave all;
清除该从服务器和主服务器之间的关系
2.如果主服务器也不维护关系了,则在主服务器上执行
reset master;

其他更多参数master-connect-retry、log-slave-updates,等可参考官方文档或者MySQL相关书籍

复制模式:

异步复制:以上演示过程,为异步复制。也就是,主库执行插入、更新、删除操作之后。会立刻告知客户端成功。但是,此时,从库可能并没有更新数据,原因可能为:

1、可能是由于主库所在的系统,还没有把内容刷新到磁盘上的binlog文件中,又或者刷新到binlog上时,磁盘损坏。导致binlog文件并没有收到内容。

2、亦或者网络原因太慢,导致IO线程,读取binlog太慢。

都会造成主从数据库在短时间内不一致。

为解决以上情况,可以使用半同步复制,即当主库更新成功之后,不会立刻返回成功,而是等待其中一个从库IO线程收到binlog文件,并成功写入到relylog中,才返回成功。当主库binlog如果迟迟推送不到从库上,则会等待一段之间之后,转为异步。等待时间长短取决于rpl_semi_sync_master_timeout设置的时间(毫秒)决定。半同步复制,只要主从库之间的网络足够快,足够稳定,从库更新数据就越实时。

 

思考:

在主从复制架构中,如何保证主从MySQL的实例的高可用?

目前开源的产品有MHA全称Master High Availability.MHA能在master宕机的情况下,迅速将其他从库中的一个升级为主库,保证主从架构的可用性。

 

如何解决主从之间的binlog传输问题?

目前业界开源的有阿里的cannal

 

拓展:

常见主从架构:

1、一主多从

2、多级复制。如果从库数量很多,主库会对每个从库建立一个binlog dump线程来将数据库变化发送给从库的I/O线程。这时候主库还要承担大量写的压力,整体压力十分大。可以使用master1->master2->slave1、slave2...slaveN这种架构。也就是说存在两个主库,主库1直接把数据推送给master2,也就是maste1只存在一个binlog dump线程.。再由master2按照一主多从的架构推给其他的从库。因为会经历两次复制(master1->master2,master2->slave),所以效率也会差一下。可以将master2将表引擎设置为BLACKHOLE。因为master2并不承担读写请求,只是做一个中转站的作用,所以推荐使用BLACKHOLE表引擎。(详细内容可参考深入浅出MySQL一书)

3、双主复制(有兴趣可以参考有关书籍)

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值