MySQL主从双向同步复制

时间:2021-10-29 17:34:12

本文介绍了mysql主从,实现mysql的双向同步复制。

MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护日志文件的一个索引以跟踪日志循环。当一个从服务器连接到主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后*并等待主服务器通知下一次更新。

为什么使用主从复制?

1、主服务器/从服务器设置增加了健壮性。主服务器出现问题时,你可以切换到从服务器作为备份。

2、通过在主服务器和从服务器之间切分处理客户查询的负荷,可以得到更好的客户响应时间。但是不要同时在主从服务器上进行更新,这样可能引起冲突。

3、使用复制的另一个好处是可以使用一个从服务器执行备份,而不会干扰主服务器。在备份过程中主服务器可以继续处理更新。

MySQL使用3个线程来执行复制功能(其中1个在主服务器上,另两个在从服务器上。当发出START SLAVE时,从服务器创建一个I/O线程,以连接主服务器并让主服务器发送二进制日志。主服务器创建一个线程将二进制日志中的内容发送到从服务器。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志。第3个线程是SQL线程,从服务器使用此线程读取中继日志并执行日志中包含的更新。SHOW PROCESSLIST语句可以查询在主服务器上和从服务器上发生的关于复制的信息。

默认中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机名,nnnnnn是序列号。用连续序列号来创建连续中继日志文件,从000001开始。从服务器跟踪中继日志索引文件来识别目前正使用的中继日志。默认中继日志索引文件名为host_name-relay-bin.index。在默认情况,这些文件在从服务器的数据目录中被创建。中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。当SQL线程执行完中继日志中的所有事件后,中继日志将会被自动删除。

从服务器在数据目录中另外创建两个状态文件--master.info和relay-log.info。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。

下面来看一下具体的配置:

一、准备服务器

由于MySQL不同版本之间的(二进制日志)binlog格式可能会不一样,因此最好的搭配组合是Master的MySQL版本和Slave的版本相同或者更低,Master的版本肯定不能高于Slave版本。

本文中,我们假设主服务器(以下简称Master)和从服务器(以下简称Slave)的版本都是5.1.35,操作系统是Centos 4.7。

假设同步Master的主机名为:master(IP:192.168.1.123),Slave主机名为:slave(IP:192.168.1.124),2个MySQL的basedir目录都是/usr/local/mysql,datadir都是:/var/lib/mysql。

二、设置同步服务器

1、设置同步Master

修改 my.cnf 文件,在

# Replication Master Server (default)

# binary logging is required for replication

添加如下内容:


#log-bin=/var/log/mysql/updatelog  server-id = 1  auto_increment_increment = 2  auto_increment_offset = 1  binlog-do-db=discuz  binlog-ignore-db=mysql  #log-slave-updates   slave-skip-errors=all

注:

slave-skip-errors 是跳过错误,继续执行复制操作

多主互备和主从复制有一些区别,因为多主中 都可以对服务器有写权限,所以设计到自增长重复问题

出现的问题(多主自增长ID重复)
1:首先我们通过A,B的test表结构
2:掉A,在B上对数据表test(存在自增长ID)执行插入操作,返回插入ID为1
3:后停掉B,在A上对数据表test(存在自增长ID)执行插入操作,返回的插入ID也是1
4:然后 我们同时启动A,B,就会出现主键ID重复

解决方法:
我们只要保证两台服务器上插入的自增长数据不同就可以了
如:A查奇数ID,B插偶数ID,当然如果服务器多的话,你可以定义算法,只要不同就可以了

在这里我们在A,B上加入参数,以实现奇偶插入

A:my.cnf上加入参数

auto_increment_offset = 1  auto_increment_increment = 2

这样A的auto_increment字段产生的数值是:1, 3, 5, 7, …等奇数ID了

B:my.cnf上加入参数

auto_increment_offset = 2  auto_increment_increment = 2

这样B的auto_increment字段产生的数值是:2, 4, 6, 8, …等偶数ID了

可以看出,你的auto_increment字段在不同的服务器之间绝对不会重复,所以Master-Master结构就没有任何问题了。当然,你还可以使用3台,4台,或者N台服务器,只要保证auto_increment_increment = N 再设置一下auto_increment_offset为适当的初始值就可以了,那样,我们的MySQL可以同时有几十台主服务器,而不会出现自增长ID重复。

重启MySQL,创建一个MySQL帐号为同步专用


# /usr/local/mysql/bin/mysql -u root -p  mysql> GRANT REPLICATION SLAVE ON *.* TO 'back'@'%' IDENTIFIED BY 'back';  mysql>GRANT FILE,SELECT,REPLICATION SLAVE ON *.* TO   'back'@'%' IDENTIFIED BY 'back';  mysql> FLUSH PRIVILEGES ;

如果想要在Slave上有权限执行 "LOAD TABLE FROM MASTER" 或 "LOAD DATA FROM MASTER" 语句的话,必须授予全局的 FILE 和 SELECT 权限:

2、设置同步Slave

修改my.cnf文件,添加


server-id = 2  auto_increment_increment = 2  auto_increment_offset = 2  master-host = 192.168.1.123  master-user = back  master-password = back  master-port = 3306  replicate-ignore-db=mysql   replicate-do-db=discuz  #log-slave-updates   slave-skip-errors=all

重启MySQL

3、启动同步

在主服务器master MySQL命令符下:


# /usr/local/mysql/bin/mysql -u root -p    mysql> show master status;  显示(当然这个是我机器的情况,你的不可能跟我一样哈,只是个例子):    +------------------+----------+-------------------+------------------+    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |    +------------------+----------+-------------------+------------------+    | mysql-bin.000009 | 98 | discuz | mysql |     +------------------+----------+-------------------+------------------+

在从服务器master MySQL命令符下:


# /usr/local/mysql/bin/mysql -u root -p  mysql> slave stop;  mysql> change master to master_host='192.168.1.123', master_user='back', master_password='back', master_log_file='mysql-bin.000009', master_log_pos=98;  mysql> slave start;  mysql> show slave status\G;    Slave_IO_Running: Yes  Slave_SQL_Running: Yes

如果都是yes,那代表已经在同步

往表里面写点数据测试一下看是否同步成功,如果不成功,绝对不是你的RP问题,再检查一下操作步骤!

4、设置双向同步

修改slave服务器的my.cnf,添加


log-bin=/var/log/mysql/updatelog  binlog-do-db=discuz  binlog-ignore-db=mysql

重启MySQL,创建一个MySQL帐号为同步专用


mysql> GRANT REPLICATION SLAVE ON *.* TO 'back'@'%' IDENTIFIED BY 'back';  mysql> GRANT FILE,SELECT,REPLICATION SLAVE ON *.* TO   'back'@'%' IDENTIFIED BY 'back';  mysql> FLUSH PRIVILEGES ;

修改master服务器的my.cnf,添加


master-host = 192.168.1.124  master-user = back  master-password = back  master-port = 3306  replicate-ignore-db=mysql  replicate-do-db=discuz

重启MySQL

在主服务器slave MySQL命令符下:

show master status;    +------------------+----------+-------------------+------------------+    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |    +------------------+----------+-------------------+------------------+    | mysql-bin.000013 | 98 | discuz | mysql |     +------------------+----------+-------------------+------------------+

在服务器A MySQL命令符下:


mysql> slave stop;  mysql> change master to master_host='192.168.1.124', master_user='back',   master_password='back', master_log_file='mysql-bin.000013', master_log_pos=98;  mysql> slave start;

其实也就是A->B单向同步的反向操作!双向同步,就这么简单啦!

提示:如果修改了主服务器的配置,记得删除从服务器上的master.info文件。否则从服务器使用的还是老配置,可能会导致错误。

-----------------------------------------------------------------------------------

注意:关于要复制多个数据库时,binlog-do-db和replicate-do-db选项的设置,网上很多人说是用半角逗号分隔,经过测试,这样的说法是错误的,MySQL官方文档也明确指出,如果要备份多个数据库,只要重复设置相应选项就可以了。

比如:


binlog-do-db=a  binlog-do-db=b  replicate-do-db=a  replicate-do-db=b

补:

#启用从库日志,这样可以进行链式复制  log-slave-updates    #从库是否只读,0表示可读写,1表示只读  read-only=1    #只复制某个表  replicate-do-table=tablename    #只复制某些表(可用匹配符)  replicate-wild-do-table=tablename%    #只复制某个库  replicate-do-db=dbname    #只复制某些库  replicte-wild-do-db=dbname%    #不复制某个表  replicate-ignore-table=tablename    #不复制某些表  replicate-wild-ignore-table=tablename%    #不复制某个库  replicate-ignore-db=dbname    #复制完的sql语句是否立即从中继日志中清除,1表示立即清除  relay-log-purge=1

http://zhumeng8337797.blog.163.com/blog/static/10076891420113192155576/