mysql - 主从复制

概念

本想把文章取名为集群(cluster),想想还是算了,称作主从复制(master-slave)会好一些,
因为 mysql 中已经存在一个 mysql-cluster,mysql 分布式版本的安装包叫这个名字。

主从复制的功能:一台主机负责写入数据,其它主机实时同步这些数据,每一台机子数据完全相同。

基本原理

简单地说,从数据库会读取主库的日志,执行与主库相同的操作,从而实现数据的同步。

master 在事务提交时,会将操作记录在二进制日志文件(binlog)中;
主库将binlog 中的日志事件,推送到从库的中继日志(relay log);
slave 根据中继日志中的事件,执行与主库一样的操作。

安全问题

从基本原理上看,就能发现弊端,极端情况下,主机宕机之前,刚好提交一个事务,从机还没收到这个信息。

对数据安全性极高的情况下,需要考虑安全性更高的半同步复制,或者组复制。

前置检查

检查 my.cnf 文件,确保所有主机的 server-id 都不相同

[mysqld]
# 软件路径
basedir=D:/soft/mysql/
# 数据路径,log/pid/sock 等文件默认都会放到这个路径
datadir=D:/soft/mysql/data/

# 文件软连接
symbolic-links=0

# 服务 id:做集群的时候,需要保证唯一
server-id = 1

# 解决高版本产生 1055 异常报错的问题
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

# binlog 日志的存储路径和文件名,一般只要写文件名,默认会放到 datadir 下
# log-bin=D:/soft/mysql/data/binlog
# 集群同步时忽略的数据库
# binlog-ignore-db=mysql

# 是否只读,1 代表只读, 0 代表读写
# read-only=0

# 监听的ip地址
# port = 3306  
# 监听端口
# bind-address = 0.0.0.0 

同步账号

专门构建一个账号,用于同步数据

# 建立账号(mysql8)
create user 'slave' identified with mysql_native_password by 'slave1122..';

# 建立账号(mysql5)
create user 'slave' identified by 'slave1122..';

# 授权
grant replication slave on *.* to 'slave';

# 刷新
flush privileges;

-- 也可以直接使用 root 账号进行同步,使用 root 账号则跳过前面步骤

主机设置

# 查看 master 当前状态
show master status;

show master status 用于查看 master 当前状态,各个字段含义如下:

  • File : binlog写到什么文件
  • Position : binlog写到什么位置
  • Binlog_Ignore_DB : 不需要同步的数据库

备用机配置

-- 设置 master 参数:binlog 文件名、初始位置等等,告诉从机从什么位置开始同步数据
change master to master_host='127.0.0.1',master_user='slave',master_password='slave1122..',master_log_file='binlog.000056',master_log_pos=157;

-- 启动同步
start slave;

-- 查看同步状态
show slave status;

-- 结束同步
stop slave;

show slave status 用于展示从主机的状态:

  • Relay_Master_Log_File:表示已经同步到那个 binlog 文件;
  • Exec_Master_Log_Pos:表示已经同步到 binlog 文件的哪个位置;
  • Slave_SQL_Running:备份线程是否启动。

Slave_IO_Running、Slave_SQL_Running 状态为 Yes,且同步位置一致,表示已经完成所有数据的同步。

重置命令(高风险)

-- 重置主机
RESET MASTER;

-- 重置从机
RESET SLAVE;

为什么说高风险,因为和一般命令不同,reset 不是重启的意思,这个命令执行完,会清空日志文件。

一定要考虑清楚,这个命令的执行后果,如果数据不一致,又把日志清空,就只能手动合并数据了。

场景一:

同步数据可以通过一些很粗暴的方式来做,比如:直接转储主库的所有数据,再导入到备用库,因为是手动操作的,启用主从之前,需要清理所有历史。

场景二:

部署过程中,更新了配置,导致 binlog 文件发生变化(比如改 binlog 文件名),需要更新同步位置,需要通过执行 reset slave 来解决这个报错。

如果因为修改配置,无法继续同步数据,一般会报错:Slave failed to initialize relay log info structure from the repository。

(更多内容见文章末尾)

相关命令

-- 查询当前的 server-id,确保不一致
SHOW VARIABLES LIKE 'server_id';


-- 服务重启
service mysql restart;

-- root 账号登录
mysql -u root -p 

主备模式

一台主机负责读写数据,另一台负责同步数据,故障的时候切换到备用主机。

单点写入,多点读取

一台主机负责读写数据,多台主机负责同步数据,所有主机允许同时读取数据,减轻数据库的压力。

(这种应用暂未找到专业名词,读写分离??)

双主模式(可以研究,但是别用)

原理还是主从复制(master-slave),是比较另类的用法,主节点和从节点,都可以进行读写,互相同步对方的数据;

因为原理也是主从,所以自然也有主从的缺陷,除此之外,是双写带来的事务冲突问题,两个节点很凑巧的改到同一条数据;

总之就是别用,一旦出现问题,一般就是大问题,数据出现差异之后,如果不产生事务冲突,短期内都不会影响使用,要等很久之后才会发现问题。

非要用的情况下,个人建议就是:允许双写,但是不写,只做单点写入,发生故障时,通过人工介入,切换到备用节点。

分布式

我们平常使用的安装包,跟分布式版本是有区别的,可以去官网下载安装包,
暂时没有这方面需求,就不再继续深入研究了,
搜索关键字 mysql-cluster,会更容易找到学习资料。

http://mirrors.sohu.com/mysql/

https://dev.mysql.com/downloads/cluster/#downloads

双主损坏案例

  1. A、B 关闭、重启,关闭过程中,不做任何更新,重启之后,双主集群状态全部正常。
  2. A 关闭一段时间,之后重启,B 保持运行,在 A 关闭期间,B 执行了很多语句,A 重启之后,双主集群状态全部正常。
  3. A 关闭一段时间,B 执行了一些语句,之后将 B 关闭;然后启动 A,也执行一些语句,然后再启动 B,如果语句存在冲突,双主集群必定异常。

总结起来,还是事务冲突导致,更新同一行记录,无法及时通知对方。

什么场景下,会导致两个节点同时异常?

  1. 将 mysql 装在容器中(k8s,swarm),如果环境不稳定,自动化部署程序会因为各种原因,去重启容器。
  2. 自动化部署,会用到一些挂载技术(NAS、NFS…),如果网络不稳定,会引起服务异常,进而重启整个服务。

重置命令(细项)

RESET MASTER:重置主节点,删除所有的 binlog 日志文件,重新开始所有新的日志文件,用于第一次进行搭建主从库时,进行主库 binlog 初始化工作。

RESET SLAVE:重置从节点,忘记主从复制的位置信息,删除 master.info 文件和 relay-log.info 文件,以及所有的 relay log 文件,重新启用一个新的 relay log 文件。

RESET MASTER removes all binary log files that are listed in the index file, leaving only a single,
empty binary log file with a numeric suffix of .000001, whereas the numbering is not reset by PURGE BINARY LOGS.

RESET MASTER is not intended to be used while any replication slaves are running.
The behavior. of RESET MASTER when used while slaves are running is undefined (and thus unsupported),
whereas PURGE BINARY LOGS may be safely used while replication slaves are running.

RESET SLAVE makes the slave forget its replication position in the master's binary log.
This statement is meant to be used for a clean start: It deletes the master.info
and relay-log.info files, all the relay log files, and starts a new relay log file.
To use RESET SLAVE, the slave replication threads must be stopped (use STOP SLAVE if necessary).

posted on 2023-09-12 11:28  疯狂的妞妞  阅读(72)  评论(0编辑  收藏  举报

导航