MySQL Dual-Master 双向同步
本文介绍的Mysql Dual-Master 复制实施方法可能不是最完美、最强大的。但是在我的应用环境下能很好的满足各项需求。
本文基于我们仅仅使用两台MySQL服务器的情况下,但是你会发现文章中介绍的方法可以很方便的应用于多台服务器的环境下。同样地,我们假设您将用于同步复制的数据库已经在其中一台MySQL服务器上建好了。最后,在开始所有工作之前,我们必须调整所有服务器的防火墙策略以保证彼此能访问对方的3306端口。
环境:
操作系统:CentOS 5.4 x86
MySQL版本:5.0.77
主服务器IP:10.10.1.1
从服务器IP:10.10.1.2
实现目标:主从两台机器MySQL数据双向同步
数据库准备工作
分别在两台服务器上执行锁表操作:
shell>mysql -u [user] -p -e "FLUSH TABLES WITH READ LOCK"
将需要配置同步的数据库Dump出来:
shell>mysqldump -u [user] -p -c [database name] > /tmp/dumpeddb.sql
将dump出来的文件拷贝到另外一台服务器上,方法随意。我用scp
shell>scp -P 22000 /tmp/dumpeddb.sql user@anothermaster:/tmp
如果这台服务器已经建好库了,那么可以直接导数据:
shell>mysql -u [user] -p -D [database name] < /tmp/dumpeddb.sql
如果还没有该库,那么再导数据之前我们需要先建库。
shell>mysql -u [user] -p -e 'CREATE DATABASE "databasename"'
最后我们需要在两台服务器上别分创建一个账号,用来同步数据。
shell>mysql -u root -p
mysql>GRANT REPLICATION SLAVE, REPLICATION CLIENT, SUPER ON databasename.* To replicate IDENTIFIED BY 'replpassword';
mysql>FLUSH PRIVILEGES;
修改my.cnf
首先,我们需求修改bind-address选项。保证mysql监听在一个可以被对方访问到的网口上,当然如果你监听在0.0.0.0上就不会有这个问题了,但是这么做通常会带来一些安全问题。我一般会让它监听内网地址
bind-address = 10.10.1.1(主服务器)
bind-address = 10.10.1.2(从服务器)
将以下内容加到主服务器的my.cnf里
- server-id = 1
- auto-increment-increment = 2
- auto-increment-offset = 1
- log-bin = /var/log/mysql/log-bin.log
- binlog-do-db = databasename
- binlog-ignore-db = mysql
- binlog-ignore-db = test
server-id = 1 auto-increment-increment = 2 auto-increment-offset = 1 log-bin = /var/log/mysql/log-bin.log binlog-do-db = databasename binlog-ignore-db = mysql binlog-ignore-db = test
server-id服务器标识,我们必须给两台机器分配不同的server-id.
log-bin,开启mysql的binlog(二进制日志).开启后mysql会将所有的修改操作记录到binlog中,可以用mysqlbinlog工具查看,里面都是一条一条的sql语句。slave I/O会读取主机的binlog,然后把读取到的内容在slave上执行,这就是mysql主从同步的基本原理。
binlog-do-db,设置哪些数据库写binlog。
binlog-ingore-db,设置哪些数据库不写binlog。
通过这两个选项我们就可以设置哪些库同步哪些库不同步。
auto-increment-incrment和auto-increment-offset这两个选项的设置是为了防止2台服务器互相复制产生关键字段的冲突。如果他们用不同的便宜,比如一个按照1,3,5,7增加而另外一台按照那个2,4,6,8增加。auto-incrment-increment=2自动增加的字段每次步进是2,auto-increment-offset=1自动增加的字段的初始值是1
将以下内容添加到从服务器
-
server-id = 2
- auto-increment-increment = 2
- auto-increment-offset = 2
- log-bin = /var/log/mysql/log-bin.log
- binlog-do-db = databasename
- binlog-ignore-db = mysql
- binlog-ignore-db = test
server-id = 2 auto-increment-increment = 2 auto-increment-offset = 2 log-bin = log-bin.log binlog-do-db = demo1 binlog-ignore-db = mysql binlog-ignore-db = test binlog-ignore-db = demo binlog-ignore-db = wang
注意这里auto_increment_offset选项的值跟主服务器上不一样。
分别重启mysql服务
shell>/etc/init.d/mysql restart
或者
shell>mysql -u root -p -e "RESET MASTER"
配置主机到从机同步
记录主机的master状态
mysql> show master status\G
*************************** 1. row ***************************
File: log-bin.log.000001
Position: 98
Binlog_Do_DB: databasename
Binlog_Ignore_DB: mysql,test
1 row in set (0.00 sec)
根据主机显示结果在从机上配置master参数
mysql>CHANGE MASTER TO
-> MASTER_HOST='10.10.1.1',
-> MASTER_USER='replicate',
-> MASTER_PASSWORD='replpassword',
-> MASTER_LOG_FILE='log-bin.log.000001',
-> MASTER_LOG_POS=98;
CHANGE MASTER TO MASTER_HOST='192.168.1.108',MASTER_USER='replicate',MASTER_PASSWORD='123456',MASTER_LOG_FILE='log-bin.000001',MASTER_LOG_POS=120;
其中MASTER_HOST、MASTER_USER、MASTER_PASSWORD这些参数可以在my.cnf里。但是我个人更喜欢在mysql里配置,一方面安全点,另一方面MASTER_LOG_FILE和MASTER_LOG_POS这些参数还是得在mysql里面配置,不如一块在myql里配置来的方便。
配置从机到主机同步(上一节的步骤反过来执行一遍)。
记录从机上的master状态
mysql> show master status\G
*************************** 1. row ***************************
File: log-bin.log.000001
Position: 98
Binlog_Do_DB: databasename
Binlog_Ignore_DB: mysql,test
1 row in set (0.00 sec)
根据从机显示的结果在主机上配置master参数
mysql>CHANGE MASTER TO
-> MASTER_HOST='10.10.1.2',
-> MASTER_USER='replicate',
-> MASTER_PASSWORD='replpassword',
-> MASTER_LOG_FILE='log-bin.log.000001',
-> MASTER_LOG_POS=98
CHANGE MASTER TO MASTER_HOST='192.168.1.109',MASTER_USER='replicate',MASTER_PASSWORD='123456',MASTER_LOG_FILE='log-bin.000001',MASTER_LOG_POS=120;
分别开启slave线程
mysql>start slave;
解锁
mysql>unlock tables;