张柏沛的个人IT技术博客-专注和分享PHP建站和Python技术的学习博客

正文内容

Mysql主从复制原理 + 快速部署主从节点

栏目:数据库 系列:无 发布时间:2021-06-05 14:21:36 浏览量:121

主从复制应用场景

  1. 主从服务器互为备份
  2. 读写分离分担压力



mysql主从复制支持不同形式,主要有如下形式:


  1. 单向主从复制



  1. 一主多从模式


PS:该模式下,从节点建议不超过5台。从节点越多,同步延迟越久,而且写入数据的时候占用带宽越大(因为要将数据要拷贝多份到多台服务器上)。


  1. 双向主从模式


PS:该模式有缺陷(如数据写入时数据冲突的问题),不建议使用。


  1. 线性级联同步模式(单向)


该模式数据只能从第一台主节点写入。级联的层数不宜超过3层,否则会造成较大的延迟。存在明显延迟也是该模式的缺陷,尤其是级联层数过长的情况。


  1. 环状级联模式(单向)


任意一台节点写入数据都能够同步到其他节点


  1. 环状级联多主多从模式(单向)


该模式用的比较少,由于其可供读和写的节点数量都比较多,所以适用于那种写压力和读压力都比较大的场景。一般模式的架构越复杂维护起来越困难,问题也越多,例如该模式如果有一个主节点挂掉,那么其下的从节点不再更新,存的就是旧数据,会出现与其他节点数据不一致的情况。该模式不建议使用,其实简单的往往是最好的。



mysql官方推荐使用 1/2/4 这几种模式的主从复制,不建议使用3/5/6。并且禁止使用两个主节点同步到一个从节点的模式,这会造成数据混乱。


需要注意的是,mysql主从复制都是异步的而不是同步的,因此数据的同步不是实时的,而是有延迟的。




mysql主从复制原理

主从复制依赖于3个线程和binlog日志

三个线程分别是:主节点上的IO线程(或binlog dump线程),从节点的IO线程和SQL线程。

binlog日志(包括mysql-bin.00001mysql-bin.00002等日志文件和mysql-bin.index日志索引文件), binlog日志的功能是记录增删改操作。需要开启log-bin功能。


主从复制配置过程:

  1. 对主节点开启log-bin功能,让binlog日志记录增删改操作。
  2. 在主节点建立repl账号,设置其权限为replication client
  3. 在同步之前,手动将主库的数据拷贝一份到从库(用mysqldump),但是此时客户端会继续向主库写入数据从而导致主从不一致。因此需要先对主库加锁,使得写请求被阻塞,等到备份完成后再释放锁。
  4. 对从库执行change master to命令设置要连接的主节点信息、repl账号信息和开始同步的位置点(position)。从节点会将这些信息记录到master.info文件中。
  5. 从库执行start slave



主从复制原理


执行start slave后,从库会创建一个IO线程和SQL线程,从的IO线程(使用repl账号)连接主节点的主进程,连接成功后,主节点会创建一个IO线程与从节点的IO线程通信。


当用户执行写操作(insert/update/delete/create/drop/alter,不含selectshow)时,数据会先写入到主库的表中,然后才写入到binglog日志中。


主从连接后,从节点的IO线程会将position(从master.info文件读取)发送给主节点的IO线程(从节点向主节点发起请求),主的IO线程根据position从指定的binlog日志文件(mysql-bin.0000n)读取position位置以后的日志内容 + 最新的position 发送给从的IO线程。主节点不一定能把要同步的日志数据一次性发送给主节点,可能会分多次传输。


从的IO线程将binlog内容写入到中继日志(relay-log.00001),将position更改到master.info中。之后从节点会继续用新的position请求主节点的binlog日志内容重复循环上面的过程。


从库的SQL线程是持续在运行的,它从relay-log中继日志中读取日志并解析为sql语句并执行。当要解析的relay-log日志内容太多时,SQL线程也可能不会一次性读取完而是先读取到某个位置,会有一个relay-log.info文件会记录这个位置方便SQL线程下次继续从这个位置读。




常规部署主从

实操步骤

1. 修改my.cnf,开启binlog日志,并且保证主从节点的(my.cnf)server-id不同。

[mysqld]
server-id = 1
log-bin = /data/3306/mysql-bin


2. 授权用户

grant replication slave on *.* to repl@'192.168.10.%' identified by "password123";

*.*表示同步所有库和所有表。

repl是同步账号,192.168.10.%是授权的能够连接主节点的网段,


flush privileges # 刷新权限
select user,host from mysql.user # 检查复制账号
show grants for repl@'192.168.10.%'


3. 锁表全备

flush table with read lock; # 会锁住当前数据库的所有表(读锁);如果超过特定时间会自动解锁,超时时间可以查看。且锁表之后,mysql客户端窗口不能关闭,否则会立刻解锁。

show variables like '%timeout%' # 查看全局锁表的超时时间

show master status # 在主节点执行,查看当前binlog的所写的binlog文件名和最新pos。该pos之后会在从节点执行change master to 时用到。

mysqldump -uroot -p -A -B --events -S /data/3306/mysql.sock> /root/rep_bak.sql   # 开一个新窗口执行,-A表示备份所有库,--events表示导入事件

unlock table # 解锁


4. 启动从节点,导入全备

mysql -uroot -p -S /data/3307/mysql.sock < /root/rep_bak.sql  # -S表示指定mysql.sock的生成位置。mysql.sock文件是当启动一个mysql客户端时生成的。

这么一来,你从库的用户信息也变成主库的用户了。


5. 执行change master to并启动同步c

hange master to master_host='主库ip', master_port=3306, master_user='repl', master_password='xxx',master_log_file='mysql-bin.00002',master_log_pos=340;    #如果设置错了,需要reset slave all再重新配置

start slave

show slave status\G;         # 主要看3项:Slave_IO_Running:Yes; Slave_SQL_Running:Yes; 这两项是从节点的IO线程和SQL线程是否启动; Seconds_Behind_Master:0 表示从库和主库的延迟秒数,0表示没有延迟,数据完全同步。


PS:上述操作请在深夜没有人访问服务的时候完成。


快速部署主从

1. 半夜执行定时任务,备份导出主库数据:

mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A -B --events -x --master-data=1|gzip > /root/repl_bak.sql.gz

-x 表示锁表备份

--master-data=1会在备份数据中增加以下语句(自动记录下binlog文件和pos)

change master to master_log_file='mysql-bin.00003',master_log_pos=107


2. 白天的时候导入全备并且开始同步

gzip -d repl_bak.sql.gz

mysql -uroot -p333333 -S /data/3307/mysql.sock < repl_bak.sql

mysql -uroot -p333333 -S /data/3307/mysql.sock << EOF

change master to

 master_host='xxx',

master_port=3306,

master_user='repl',

master_password='6666';

EOF



start slave


mysql主从复制的问题汇总

1. 主库 show master status; 没有返回结果

是因为主库binlog没有开启或开启失败


可查看 show variables like "log_bin"


2. 启动mysql服务失败

原因是启动脚本对mysql.sock是否存在做了判断,如果存在mysql.sock,启动脚本就认为服务运行是个小bug,此时可以删除mysql.sockpid文件然后重新启动。


3. 如何查看mysql开启的线程信息

show processlist; # 主库和从库都可以执行



主库IO线程工作状态

Sending binlog event to slave #正在发送binlog给从节点


Finished reading one binlog; switching to next binlog  # 主节点已经发送完上一个binlog内容,正在打开下一个要发送到从节点的binlog文件


Has sent all binlog to slave; waiting for binlog to be updated   # 线程已将所有binlog同步到从节点。线程此时为空闲状态,等待主节点上binlog的更新。


Waiting to finalize termination # 线程停止时发生的状态


更多状态可以查看mysql官方文档


从库IO线程工作状态

Waiting for master to send event # 线程已经连接上主节点,等待binlog日志到达


Reconnecting after a failed binlog dump request # 尝试重新连接主节点


Queueing master event to the relay log # 正在将binlog写入到中继日志


Requesting binlog dump # 向主节点请求binlog日志和最新的pos


更多状态可以查看mysql官方文档


从库SQL线程工作状态

Has read all relay log; waiting for the slave IO thread to update it # SQL线程已处理完所有中继日志的事件,正在等待IO线程将新事件写入中继日志。


Reading event form the relay log # SQL 线程正在读取中继日志的事件并执行


PS:主节点下有几个从节点就会开启几个IO线程。如果一个主节点下面有3个从节点,那么这个主节点会开启3IO线程。



4.如果发现主从不同步怎么办

如果是因为执行命令错误导致主从同步断开,如主库insert了一条重复数据导致报错使得主从同步断开。这些都可以通过 show slave status查看。


stop slave

set global sql_slave_skip_counter = 4 # 将同步指针往下移动多个,至于是多少个就看主库的报错有多少个,可以多次尝试

start slave

show slave status # 如果还是没有同步成功,就重复上面的步骤


但是最好的做法就是一开始同步的时候在从节点设置忽略错误:

slave-skip-errors=1032,1062,1007 # 设置忽略的错误号

slave-skip-errors=all # 忽略所有错误(不推荐,会忽略不可预知的致命错误而我们还无法察觉)

slave-skip-errors=ddl_exist_errors  # 忽略ddl错误。等同于1007,1008,1050,1051,1054,1060,1061,1068,1094,1146


其他可能引起复制故障的问题:

执行mysql命令导致的报错

不同数据库版本,低版本为主高版本为从可以,高版本为主低版本为从不行

如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > Mysql主从复制原理 + 快速部署主从节点

热门推荐