主从复制应用场景
mysql主从复制支持不同形式,主要有如下形式:
PS:该模式下,从节点建议不超过5台。从节点越多,同步延迟越久,而且写入数据的时候占用带宽越大(因为要将数据要拷贝多份到多台服务器上)。
PS:该模式有缺陷(如数据写入时数据冲突的问题),不建议使用。
该模式数据只能从第一台主节点写入。级联的层数不宜超过3层,否则会造成较大的延迟。存在明显延迟也是该模式的缺陷,尤其是级联层数过长的情况。
任意一台节点写入数据都能够同步到其他节点
该模式用的比较少,由于其可供读和写的节点数量都比较多,所以适用于那种写压力和读压力都比较大的场景。一般模式的架构越复杂维护起来越困难,问题也越多,例如该模式如果有一个主节点挂掉,那么其下的从节点不再更新,存的就是旧数据,会出现与其他节点数据不一致的情况。该模式不建议使用,其实简单的往往是最好的。
mysql官方推荐使用 1/2/4 这几种模式的主从复制,不建议使用3/5/6。并且禁止使用两个主节点同步到一个从节点的模式,这会造成数据混乱。
需要注意的是,mysql主从复制都是异步的而不是同步的,因此数据的同步不是实时的,而是有延迟的。
mysql主从复制原理
主从复制依赖于3个线程和binlog日志
三个线程分别是:主节点上的IO线程(或binlog dump线程),从节点的IO线程和SQL线程。
binlog日志(包括mysql-bin.00001、mysql-bin.00002等日志文件和mysql-bin.index日志索引文件), binlog日志的功能是记录增删改操作。需要开启log-bin功能。
主从复制配置过程:
主从复制原理
执行start slave后,从库会创建一个IO线程和SQL线程,从的IO线程(使用repl账号)连接主节点的主进程,连接成功后,主节点会创建一个IO线程与从节点的IO线程通信。
当用户执行写操作(insert/update/delete/create/drop/alter,不含select和show)时,数据会先写入到主库的表中,然后才写入到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不同。
2. 授权用户
*.*表示同步所有库和所有表。
repl是同步账号,192.168.10.%是授权的能够连接主节点的网段,
3. 锁表全备
4. 启动从节点,导入全备
这么一来,你从库的用户信息也变成主库的用户了。
5. 执行change master to并启动同步c
PS:上述操作请在深夜没有人访问服务的时候完成。
快速部署主从
1. 半夜执行定时任务,备份导出主库数据:
-x 表示锁表备份
--master-data=1会在备份数据中增加以下语句(自动记录下binlog文件和pos):
change master to master_log_file='mysql-bin.00003',master_log_pos=107
2. 白天的时候导入全备并且开始同步
mysql主从复制的问题汇总
1. 主库 show master status; 没有返回结果
是因为主库binlog没有开启或开启失败
可查看 show variables like "log_bin"
2. 启动mysql服务失败
原因是启动脚本对mysql.sock是否存在做了判断,如果存在mysql.sock,启动脚本就认为服务运行是个小bug,此时可以删除mysql.sock和pid文件然后重新启动。
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个从节点,那么这个主节点会开启3个IO线程。
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命令导致的报错
不同数据库版本,低版本为主高版本为从可以,高版本为主低版本为从不行