MySQL主从复制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL主从复制相关的知识,希望对你有一定的参考价值。
主从架构中:从node是不接受w操作的,否则可能会导致数据不一致。
一、复制架构中应该注意的问题:
1.限制slave为只读模式
可以设置在启动参数中。
> show global variables like ‘read_only‘;
此限制对拥有SUPER权限的用户都无效。
阻止所有用户:
mysql> flush tables with read lock; //将阻塞所有w操作。
//但是中继日志的重放是可以的,不会被阻塞
2.如何保证主从复制的事务安全?
master在执行事务后,应该立即写入都事务日志。
二进制日志在内存中是有缓冲的。//一旦master宕机,slave仍然没有获取该事务,但是client已经commit,数据不一致
方法://保证master尽快将事务保存到二进制日志
1)在master启动参数:
sync_binlog=ON //立即刷写二进制日志
如果用到innodb存储引擎:
innodb_flush_logs_at_trx_commit=ON
innodb_support_xa=ON
1.在事务提交时立即将事务日志缓冲区中与事务日志相关的数据刷写到事务日志中去
2.xa:分布式事务,基于2段式提交,执行分布式事务。
2)在slave节点上
skip_slave_start=OFF
//在slave启动时,是否自动启动复制线程
//为了事务安全:不建议启动,直接加入很有可能会导致出错
//建议手动启动。该线程
//参考http://www.2cto.com/database/201307/230420.html
//注意:怎么强调数据的安全性都不为过。
slave:
/var/lib/mysql/
master.info :master的账号密码信息,复制位置等
relay-log.info 从节点自己记录的,复制到哪个二进制日志的哪个position步骤。
show global variables like ‘%relay_log%‘;
relay_log_info_file //保存的文件
sync_relay_log
sync_relay_log_info //
master
show global varibales like ‘%master%‘;
sync_master_info 0
//master.info中的信息是否同步到磁盘,从而让slave获取最新信息。
//有必要启动。
小结:
master:
sync_master_info
slave:
sync_relay_log
sync_relay_log_info
问题2:思考
如果master已经运行一段时间,且有大量数据,
如何配置并启动slave
方法:
通过备份恢复数据至从服务器
复制起始位置为备份时,二进制日志文件及其pos
二、如何进行主主复制:
A和B:都同时启动relay-log,binary-log,并互为主从
问题:
1.数据不一致,因此,慎用//选择其中一个,删除另外一个
2.auto_increment,A和B都在自动增长,合并将会出错。
//注意mysql 5.5及其之后的版本,在主主模型中 auto_increment 这个问题已经解决,不需要单独设定
A:奇数增长:
auto_increment_offset=1
auto_increment_increment=2
//从1开始,一次增长2个
B:偶数增长: auto_increment_offset=2
//左右不均衡怎么办?没有办法
auto_increment_offset=2
auto_increment_increment=2
//从2开始,一次增长2个
3.循环复制
配置步骤:
1.各node使用一个唯一server-id
2.都启动binary log和relay log
3.创建拥有复制权限的用户账号
4.定义自动增长id字段的数值为奇偶
5.均把对方指定为主node,并启动复制线程
步骤:
master A:
systemctl stop mariadb
rm -rf /var/lib/mysql/*
vim my.cnf
[mysqld]
log-bin=master-bin
lelay_log=relay-log
server-id=1
innodb_file_per_table=ON
skip_name_resolve=ON
auto_increment_offset=1
auto_increment_increment=2
systemctl start mariadb
mysql> show global variables like ‘%log%‘ //relay_log,log_bin
msyql> grant replication slave,replication client on *.* to ‘repluser‘@‘192.168.1.%‘ identified by ‘replipass‘;
mysql> flush privileges;
//现在两个都是干净的
show master status //查看对方处于什么位置
master-bin.000003 506
change master to master_host=‘192.168.1.68‘,master_user=‘repuser‘,master_password=‘replpass‘,master_log_file=‘master-bin.000003‘,
master_log_pos=506; //从master的这个位置开始
show slave status;
start slave;
master B:
systemctl stop mariadb
rm -rf /var/lib/mysql/*
vim my.cnf
[mysqld]
log-bin=master-bin
lelay_log=relay-log
server-id=5 //不一样
innodb_file_per_table=ON
skip_name_resolve=ON
auto_increment_offset=2 //不一样
auto_increment_increment=2
systemctl start mariadb
msyql> show global variables like ‘%log%‘; //relay-log,log-bin
msyql> grant replication slave,replication client on *.* to ‘repluser‘@‘192.168.1.%‘ identified by ‘replipass‘;
mysql> flush privileges;
mysql> show master status //查看自己处于什么位置
mysql> show master status ;
master-bin.000003 506 //也是506
change master to master_host=‘192.168.1.67‘,master_user=‘repuser‘,master_password=‘replpass‘,master_log_file=‘master-bin.000003‘,
master_log_pos=506; //从master的这个位置开始
show slave staus;
start slave;
=======================================
测试:
A:create database mydb;
show slave status;
B: use mydb;
create table tb1(id int unsigned not null auto_increment primary key,name char(30))
desc tb1;
show master status;
A:查看show slave status,二进制日志的位置已经发生改变
insert into tb1 (name) values (‘yang kang‘),(‘yang guo‘);
select * from tb1;
A:插入数据,
insert into tb1 (name ) ,,,,
最后:
select * from tb1;
1,3,5,6,8,10 //有一个内置的函数,保存了插入的id号
可以重置insert id即可
这样:就不需要在mariadb-server启动的时候指定
auto_increment_increment=2 ,...
三、半同步复制 //借助于插件
5.5版本之后的
master只等待一个slave返回复制确认结果即可//
假如没有任何一个节点返回同步成功消息:?
设置超时时间。超时后自动降级为异步模式
基于mariadb插件
/usr/lib64/mysql/plugin/
[[email protected] mysql]# ls /usr/lib64/mysql/plugin/sem*
/usr/lib64/mysql/plugin/semisync_master.so
/usr/lib64/mysql/plugin/semisync_slave.so
//一个是master节点的,一个是slave节点的
A:systemctl stop mariadb
rm -rf /var/lib/mysql/*
vim my.cnf
log-bin=master-bin
server-id=1
innodb_file_per_table=ON
skip_name_resolve=ON
systemctl start mariadb
msyql> grant replication slave,replication client on *.* to ‘repluser‘@‘192.168.1.%‘ identified by ‘replipass‘;
mysql> flush privileges;
mysql> flush privileges //slave是不需要创建该用户的
mysql-bin.00003 496
install plugin rpl_semi_sync_master SONAME ‘semisync_master.so‘;
show plugins //查看插件
show global variables like ‘%semi5‘; //多了好几个变量
show global status like ‘%semi%‘
。。client //有多少个半同步node
set global rpl_semi_sync_master_enabled=1
B:systemctl stop mariadb
rm -rf /var/lib/mysql/*
vim my.cnf
relay_log=relay-log
server-id=2
innodb_file_per_tab=ON
skip_name_resolve=ON
systemctl start mariadb
change master to master_host=‘192.168.1.67‘,master_user=‘repuser‘,master_password=‘replpass‘,master_log_file=‘master-bin.000003‘,
master_log_pos=496; //从master的这个位置开始
install plugin rpl_semi_sync_slave SONAME ‘symisync_slave.so‘;
set global rpl_semi_sync_slave_enabled=1 //启用
start slave;
show slave staus;
//再次在A上查看,...client 为1 .... master_status=ON
注意:help install
[mysqld]
plugin_dir=/path/to/plugin/directory //默认/usr/lib64/mysql/plugin
测试:
A:master
msyql> create table tb1 (id int,name char(30));
msyql> show global status like ‘%semi%‘;
将会有很多的状态等待时间。
小结:
建议只配置一个半同步。
master:
mysql> install plugin rpl_semi_sync_master SONAME ‘semisync_master.so‘;
mysql> set global variables rpl_semi_sync_master_enabled=1;
mysql> show gloabl variables like ‘%semi%‘;
mysql> show global status like ‘%semi%‘;
slave:
msyql> install plugin rpm_semi_sync_slave SONAME ‘semisync_slave.so‘;
msyql> set global variables rpl_semi_sync_slave_enabled=1;
四、复制过滤器:
msyql可以复制复制一个或多个数据库
复制过滤器可以在master和slave node做
在master上:会导致master的二进制日志不完整,不是记录了所有数据库的数据
让从节点仅复制指定的数据库,或指定数据库的指定表//但是master会发送所有的二进制数据给slave,由slave决定选择部分复制。
实现:
(1)主服务仅向二进制日志中记录与特定数据库(特定表)相关的事件
问题:时间 还原无法实现,不建议使用
binlog_do_db //数据库白名单列表
binlog_ignore_db //数据库黑名单列表,这两个不要同时使用,
(2)slave sql_thread在replay中继日志中的事件时,仅读取与特定数据库(特定表)相关的事件并应用于本地。
问题:会带来网络及磁盘IO浪费
replicate_do_db //白名单,逗号隔开
replicate_ignore_db //忽略的数据库
实现: //在原有的主从架构上
mysql> show global variables like ‘replicate%‘
mysql> set global replicate_do_db=‘mydb‘ ;
//在slave上进行过滤
mysql> show slave status \G;
//测试在master上创建其他数据库
//在slave上是看不到的,但是master在mydb上插入数据,在slave上是可以看到的
注意:show slave status \G;
replicate_ignore_table;
replicate_do_table; //限制可以单个表
replicate_do_db:
replicate_ignore_db;
replicate_wild_do_table; //通配符
replicate_wild_ignore_table; //通配符
基于SSL的复制
help change master //
change master master_ssl //指定使用ssl进行复制
查看是否支持:
mysql> show global variables like ‘%ssl%‘; //为了安全起见,在前端应用到mysql之间使用ssl
前提:支持SSL
(1)master配置证书的私钥;并且要创建一个要求必须私用SSL连接的复制账号
help grant;
grant ... with ssl_option ssl_option
//一般是slave验证master的状态
(2)slave端使用change master to 命令时指明ssl相关选项;
跟复制功能相关的文件:
master.info :用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等
relay-log.info:保存在当前slave节点上已经复制的二进制日志和本地relay log日志的对应关系
五、MySQL复制的监控和维护:
(1)清理日志:
purge binary logs to ‘mysql-bin.010‘;
purge binary logs before ‘2008-04-01 10:00:12‘;
show binary logs;
(2)复制监控
show master status;
show binlog events;
show binary logs;
show slave status;
show process list; //查看复制线程
(3)从server是否落后于master服务
slave:
show slave status;
Second_Behind_master;//落后于master多长时间。
(4)如何确定主从节点是否一致
percona-tools //一个工具可以检测
(5)数据不一致如何修复
1.slave数据删除,在master上重新备份
2.多个slave,灰度模式,逐个上下线
重新复制。
六、读写分离器
//开源实现方案,有的公司自己开发或者在前端应用实现读写分离
mysql-proxy //很多坑,已经不用
http://www.cnblogs.com/phpstudy2015-6/p/6687480.html#_label1
阿里巴巴的cobar
360的atlas
golang的kingshard
http://blog.csdn.net/hu_wen/article/details/53635976
mysql-router:官方提供,不支持读写分离,
它实现了失败转移和失败切换,而且这个工具有自己的ip和端口,实现了高可用。
算法:轮训,加权轮训等
七、如何添加一个新的salve
1 dump主库master的数据,停止slave。
mysqldump -uroot -p --all-databases > all.sql
show master status;
mysql-bin.000002 652
2 传递到从库slave上,然后在从库slave上进行还原。
mysql > stop slave;
# msyql < all.sql;
change master to master_host=‘192.168.1.106‘,master_user=‘repluser‘,master_password=‘replpass‘
,master_log_file=‘mysql-bin.000002‘,master_log_pos=652,master_connect_retry=5;
msyql> start slave;
备注:reset slave //重置slave
附件:如何切换slave为master
注意:
1.mysqlhotcopy 只能对MyISAM表进行热备
2.原理:先将需要备份的数据库加上一个读锁,
然后用FLUSH TABLES将内存中的数据写回到硬盘上的数据库,
最后,把需要备份的数据库文件复制到目标目录
mysqlhotcopy [option] dbname1 dbname2 backupDir/
以上是关于MySQL主从复制的主要内容,如果未能解决你的问题,请参考以下文章