主从同步
原理: 主库通过开启binlog日志功能,然后从库IO进程监听主库binlog的当前偏移量,如果不同就获取日志信息,并让从库执行这日志中的命令
工作过程: 首先做出从同步前,两个库的数据结构必须一模一样,然后主库开启binlog功能,当有一个修改指令生效后,binlog就会被修改,当其被修改,其当前的pos偏移量就会变化,这时候从库的IO进程发现,偏移量和自己记录的不相同,从库就会通过IO进程远程连接主数据库,获取从自己记录的偏移量开始的binlog中的内容,并记录到从库的中继日志中,最后SQL进行执行日志内容。
结构模式:
模式名称 | 介绍 | 优点 | 缺点 |
单向复制(一主一从) | 一个主库一个从库,从库同步记录主库的操作 | 最简单廉价的主从模型 | 任何一个单点故障都会破坏主从结构 |
一主多从 | 一个主库多个从库,多个从库一起同步主库 | 多个从库可以提高信息冗余安全 | 如果主库单点故障就会让所有的从库报错 |
链式复制(主从从) | 一个主库,一个主从库,一个从库 | 主从库作为主库的从库,保证其数据安全,从库作为主从库的从库,保证其安全,这样,如果主库出故障,主从库和从库依然可以工作 | 如果主从库单点故障就会让从库报错 |
互为出从(主主) | 两个数据库互相都是对方的主库,也是对方的从库 | 如果三个设备都实现主主,就可以单点故障 | 严重浪费资源 |
配置主从同步
0. 确认搭建主从同步前必须先要让从库所有数据和主库一样,
如果不一样,用mysqldump对主库进行完全备份,然后在从库上执行同步操作。
1. 配置主库
1.1 启用binlog
修改配置文件: /etc/my.cnf 启动binlog日志功能
log_bin=[ 日志存储位置/ ]日志名(自定义,不过最好每个数据的不一样,有一定标示型;不写日志位置默认存在/var/lib/mysql/下)
server_id=编号(每个数据库要都不一样)
binlog_format="mixed"
1.2 用户授权
mysql> grant replication slave on *.* to repluser@'%' identified by '密码';
1.* 查看当前正在使用的binlog日志(前往从库,进行远程登陆)
[root@mysql_slave ~]# mysql -h 主库IP -u repluser -p密码
2. 配置从库
2.1 指定server_id
修改my.cnf配置文件,只需要添一行 server_id=编号 ,这编号和主库不能一样
2.2 指定主库信息(对从库自己的数据库进行配置)
mysql> change master to
master_host='主库的IP', master_user='repluser', master_password='密码',
master_log_file='主库的日志', master_log_pos='主库的偏移量';
master_host | 指定主库 |
master_user | 指定用什么用户登陆 |
master_password | 配置从库登陆主库的密码(主库配置设置的密码) |
master_log_file | 指定主库的日志,最好在主库上用show master status查看,然后复制到这里出来 |
master_log_pos | 指定主库的偏移量,最好在主库上用show master status查看,然后复制到这里出来 |
2.3 启动slave程序
mysql> start slave;
# 停止的命令是 stop slave;
2.* 查看slave程序状态(查看 Slave_IO_Running 、 Slave_SQL_Running 是否成功打开)
mysql> show slave status\G;
总结:
配置主库: 开启binlog(包括server_id) 、 授权一个给从库连接的用户
配置从库: 给自己指定一个server_id 、 修改指定主库的信息 、 开启slave服务
注意点:
1. 主从同步中,如果从库出现故障,一段时间没有办法进行同步,在过段时间后,进行再次连接进行同步后,会把原来没有同步的部分也同步上,因为一旦从库发现偏移量不同,就会进行同步,而且同步的范围是从从库记录的偏移量,也就是断开连接前记录的最后一个偏移量,所以他能在恢复连接后完成所有同步操作;
2. 主从同步的命令不会记录在 从库 的binlog日志上,也就是说从库即使打开量binlog,如果没有特殊配置,那么从库同步后执行的所有SQL命令并不会记录到自己的binlog日志中。
一主多从
原理: 多个数据库作为从库,连接一个主库,主库发生修改后,所有从库会立刻跟着修改
配置: 先要配置一个主库,配置完成后让每个从库都像刚刚步骤配置一模一样即可
作用: 任意一个从库出现问题都不会影响主从结构。
主从从
原理: 让一个数据库服务器,即做从库,也做主库,这个主从库连接主库,做这主库的从库,同步其操作,然后再让其他数据库服务器做自己的从库,形成链式结构
举例解释: 假如现在有三个数据库服务器a、b、c ,a作为主库用来和客户端连接,b作为直接连接主库的从库,同步a库中的所有操作,然后c也是从库也想同步a库操作,只不过这次他不做a的从库,而是做b库的从库,这样a库发生数据变化,b库同步a库操作,c库同步b库操作,间接的让c库和a库实现同步。
配置: 先要配置一个主库,然后配置一个连接主库的从库,然后让该从库成为一个主库,最后让另外一个从库连接这个主从库。
其他操作就不具体说,和主从同步的操作由于,单独说一下连接主库后的从库如何开启主库功能
主从库修改,其作为主库的配置文件/etc/my.cnf,修改如下
log_slave_updates
server_id=编号(每个数据库要都不一样)
log_bin=[ 日志存储位置/ ]日志名
binlog_format='mixed'
所以配置主从从,唯一要解决的问题就是,主从库同步的命令不会写入主从库的binlog文件中,如果主从库的binlog文件不变,从库也就没办法实现同步。配置中的log_slave_updates就是让IO监听后传递的日志信息不单单发给中继日志,也发给binlog日志。
限定同步某个具体库
主库:修改配置文件/etc/my.cnf
# 允许同步的库
binlog_do_db=库名列表
# 不允许同步的库
binlog_ignore_db=库名列表
从库:修改配置文件/etc/my.cnf
# 指定只同步的库
replicate_do_db=库名列表
# 指定不同步的库
replicate_ignore_db=库名列表
复制模式 | 模式执行特点 | 优点 | 缺点 | |
异步复制 | 主库执行完一次事务后,立刻返回数据给客户端,不关心从库是否接收 | 回复速度极快 | 不管主从结构,容易数据丢失 | |
全同步复制 | 主库执行完一次事务,且所有从库都执行完,再返回数据给客户端 | 主从结构稳定,数据保存完整 | 回复速度极慢 | |
半同步复制 | 主库执行完一次事务,且至少有一个从库执行完,再返回数据给客户端 | 介于异步和全同步间,所以比较均衡 |
默认不做配置,都是异步复制的方式。
如何配置半同步复制
临时启动(即时生效)
1. 启动动态加载模块
# 查看是否支持模块 (主库和从库都要查看)
mysql> show variables like 'have_dynamic_loading';
# 如果是yes就不用操作,如果是no就在配置中进行修改 (数据库默认打开了)
2. 安装插件
# 主库安装
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
# 从库安装
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
3. 查看插件情况
mysql> select plugin_name, plugin_status from information_schema.plugins where plugin_name like '%semi%';
4. 启用半同步复制
# 主库启动
mysql> set global rpl_semi_sync_master_enabled=1;
# 从库启动
mysql> set global rpl_semi_sync_slave_enabled=1;
5. 查看半同步状态
mysql> show variables like 'rpl_semi_sync_%_enabled';
永久启用半同步复制
修改主配置文件 /etc/my.cnf
# 对主库配置
[root@mysql ~]# sed -i '/\[mysqld\]/aplugin-load=rpl_semi_sync_master=semisync_master.so' /etc/my.cnf
sed -i '/\[mysqld\]/arpl_semi_sync_master_enabled=1' /etc/my.cnf
# 对从库配置
[root@mysql ~]# sed -i '/\[mysqld\]/aplugin-load=rpl_semi_sync_slave=semisync_slave.so' /etc/my.cnf
sed -i '/\[mysqld\]/arpl_semi_sync_slave_enabled=1' /etc/my.cnf
# 如果数据库即是主库又是从库
[root@mysql ~]# sed -i '/\[mysqld\]/aplugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"' /etc/my.cnf
sed -i '/\[mysqld\]/arpl_semi_sync_master_enabled=1' /etc/my.cnf
sed -i '/\[mysqld\]/arpl_semi_sync_slave_enabled=1' /etc/my.cnf
重启数据库服务即可生效
把从库撤除出来,让其独立工作
主库: (其实没必要修改,撤除从库即可)
1. 删除用于给从库连接的用户repluser
2. 看情况关闭binlog
从库:
1. 停止服务
[root@mysql_slave ~]# systemctl stop mysqld
2. 删除相关文件
[root@mysql_slave ~]# cd /var/lib/mysql
[root@mysql_slave ~]# rm -f 主机名-relay-bin.* relay-log.info master.info
3. 重启服务
[root@mysql_slave ~]# systemctl restart mysqld
把从库撤除出来,让其独立工作
主库: (其实没必要修改,撤除从库即可)
1. 删除用于给从库连接的用户repluser
2. 看情况关闭binlog
从库:
1. 停止服务
[root@mysql_slave ~]# systemctl stop mysqld
2. 删除相关文件
[root@mysql_slave ~]# cd /var/lib/mysql
[root@mysql_slave ~]# rm -f 主机名-relay-bin.* relay-log.info master.info
3. 重启服务
[root@mysql_slave ~]# systemctl restart mysqld
排错思路:
主库:
1. 查看自己的mysql库中user表,看看也没有创建给从库连接的用户repluser
2. 查看自己的binlog日志是否正常工作
从库:
1. 查看配置文件中的server_id信息
2. 尝试用命令拿指定的用户和密码连接主库
3. 查看slave状态 ( show slave status )
4. 如果IO出错查看slave的报错信息,可能是编号(偏移量)有问题,也可能是日志名写错了
5. 如果SQL出错,可能是没有做主从同步前让两个数据库的所有内容完全相同