先展示下最终实现的配置
主1的配置(重要的,其他略)
log-bin = mysql-bin #必须要有binlog
auto_increment_offset = 1 #自增ID的初始值
auto_increment_increment = 2 #自增ID的步长(每次自动增加的数)
server-id=1 #server-id 主库从库要不同
replicate-do-db=haha #作为slave时(SQL线程)将要复制(同步)的数据库
replicate-wild-do-table=haha.user #作为slave时(SQL线程)将要复制(同步)的数据库的数据表
#以上两个配合使用,就指定只有该表同步了
master-host = 192.168.56.14 # 设置master的参数,略
master-user = rep
master-password = 123321
master-port = 3306
除此之外你的业务也要有相应的配置,也就是说(要同步的)数据库的表要设置自增ID,如
mysql> create table user(
-> userid int(4) primary key not null auto_increment,
-> username varchar(16) not null,
-> userpassword varchar(32) not null
-> );
如上例中的 auto_increment
主2的配置
log-bin = mysql-bin #必须要有binlog
auto_increment_offset = 2 #自增ID的初始值,注意和主区别
auto_increment_increment = 2 #自增ID的步长(每次自动增加的数)
server-id=2 #server-id 主库从库要不同
replicate-do-db=haha #作为slave时(SQL线程)将要复制(同步)的数控库
replicate-wild-do-table=haha.user #作为slave时(SQL线程)将要复制(同步)的数控库
#以上两个配合使用,就指定只有该表同步了
#多个表就写多个,如haha.user123
master-host = 192.168.56.13 # 设置master的参数,略
master-user = rep
master-password = 123321
master-port = 3306
重启数据库,重启slave线程
测试,达到需求.
思想:
不要在主库使用 --binlog-do-db 和 --binlog-ignore-db 来限制从库要复制库
要在从库使用replicate-do-db 和 replicate-wild-do-table 限制同步的库
详解
ID自增问题
多主互备和主从复制有一些区别,因为多主中都可以对服务器有写权限,所以设计到自增长重复问题
出现的问题(多主自增长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重复。
指定表的同步
我看到很多人用binlog-do-db, binlog-ignore-db, replicate-do-db, and replicate-ignore-db来过滤哪些库需要主从复制。虽然这4个参数确实能这样做,但我看来这样做是危险的。这4个参数被滥用了。在很多情 况下,这有更好安全的选择。
为什么危险很简单: 他们并不像你想的那样工作. 想象如下的场景: 你设置了 binlog-ignore-db = garbage, 所以garbage数据库(在slave上不存在这个数据库) 中的数据不会被复制。
现在请按操作:
$ mysql
mysql> delete from garbage.junk;
mysql> use garbage;
mysql> update production.users set disabled = 1 where user = "root";
复制会broke2次, 第一次,因为 slave尝试着去执行第一条语句,但是slave上并没有这样的表”garbage.junk” , 第二次, 隐含的, 因为对production.users表的操作不会被复制,所以root帐号并没有在slave上被禁用掉。
为什么? 因为 binlog-ignore-db 并不像你想的那样执行, 我之前说的, “garbage数据库上的数据不会被复制”是错的, 实际上(数据库)并没有这么做。事实上,他是通过“use 数据库”这种方式来过滤掉到哪些数据库操作不记录到binlog中去的。换句话说, 过滤不是基于查询的字符串的, 而是基于你used的数据库。
mysql> use garbage;
mysql> update production.users set disabled = 1 where user = "root";
我提到的其它配置选项也是类似. binlog-do-db 和 binlog-ignore-db 语句是特别危险的,因为它们不将指定的数据库操作写入到binary日志,导致你不能使用二进制日志从备份恢复指定时间的数据。
安全的替换方案是在 slave上配置过滤, 使用基于查询中真正涉及到的表的选项, 这些是: replicate-wild-* 选项, 例如, 避免复制 garbage数据库中的数据的安全的方案是 配置: replicate-wild-ignore-table=garbage.%. 这样做仍然有一些特殊的情况, 不能正常工作,但可以在更多的情况下正常工作,并且会遇到更少的意外 (gotchas)。