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主从复制文档,可参见官方文档,里面的步骤说的已经很详细了

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

MySQL主从复制(详细过程以及从库不能同步的解决办法)_第1张图片

可以将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';

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

MySQL主从复制(详细过程以及从库不能同步的解决办法)_第2张图片

在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;

显示如下图:

MySQL主从复制(详细过程以及从库不能同步的解决办法)_第3张图片

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

3.设置好之后,启动slave

start slave;

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

show processlist \G

MySQL主从复制(详细过程以及从库不能同步的解决办法)_第4张图片

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实例保持一致

MySQL主从复制(详细过程以及从库不能同步的解决办法)_第5张图片

可以看到,这里的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、一主多从

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、双主复制(有兴趣可以参考有关书籍)

你可能感兴趣的:(数据库)