参考:
http://dev.mysql.com/doc/refman/5.1/en/replication-options-slave.html
http://blog.chinaunix.net/uid-26446098-id-3267556.html

一、 环境
master1 192.168.11.100
CentOS release 6.2

master2 192.168.11.110
CentOS release 6.2

二、软件安装
yum -y install mysql-server perl lua

三、配置
1、基本目录准备
两台服务器分别执行
数据目录和binlog目录
[root@master1 ~]# mkdir -p /data/mysql/binlogs && chown -R mysql.mysql /data/mysql/
日志目录
[root@master1 ~]# mkdir /data/logs/mysql/ && chown -R mysql.mysql /data/logs/mysql/
binlog目录

2、配置
两台服务器分别执行
[root@master1 ~]# egrep -v '^#|^$' /usr/share/doc/mysql-server-5.1.69/my-huge.cnf > /etc/my.cnf
[root@master2 ~]# egrep -v '^#|^$' /usr/share/doc/mysql-server-5.1.69/my-huge.cnf > /etc/my.cnf
master1配置文件
[root@master1 ~]# cat /etc/my.cnf
### NO-3306 Master ###
[mysqld]
datadir = /data/mysql/
port = 3306
socket = /data/mysql/mysql.sock
pid-file = /data/mysql/mysql.pid

#log
log-error = /data/logs/mysql/3306_error.log
long_query_time = 2
slow-query-log-file = /data/logs/mysql/3306_slow.log

log-bin = binlogs/mysql-bin
binlog_format = ROW
relay-log = binlogs/mysql-relay-bin

#data
innodb_data_file_path = ibdata1:500M;ibdata2:500M:autoextend
innodb_buffer_pool_size = 256M
innodb_additional_mem_pool_size = 50M
innodb_log_file_size = 256M
innodb_open_files = 500
back_log = 1000
join_buffer_size = 8M
query_cache_size = 16M
read_buffer_size = 4M
sort_buffer_size = 8M
innodb_thread_concurrency = 8

character_set_server = utf8
init-connect = 'SET NAMES utf8'

replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = performance_schema

skip-name-resolve

skip-external-locking
slave-skip-errors = all
server-id = 33061
log-slave-updates = 1

[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

master2 配置文件 和master一样 不过是serverid增加1

### NO-3306 Master backup ###
[mysqld]
datadir = /data/mysql/
port = 3306
socket = /data/mysql/mysql.sock
pid-file = /data/mysql/mysql.pid

#log
log-error = /data/logs/mysql/3306_error.log
long_query_time = 2
slow-query-log-file = /data/logs/mysql/3306_slow.log

log-bin = binlogs/mysql-bin
binlog_format = ROW
relay-log = binlogs/mysql-relay-bin

#data
innodb_data_file_path = ibdata1:500M;ibdata2:500M:autoextend
innodb_buffer_pool_size = 256M
innodb_additional_mem_pool_size = 50M
innodb_log_file_size = 256M
innodb_open_files = 500
back_log = 1000
join_buffer_size = 8M
query_cache_size = 16M
read_buffer_size = 4M
sort_buffer_size = 8M
innodb_thread_concurrency = 8

character_set_server = utf8
init-connect = 'SET NAMES utf8'

replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = performance_schema

skip-name-resolve
skip-external-locking
slave-skip-errors = all
server-id = 33062
log-slave-updates = 1

[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

四、初始化数据库并启动
1、初始化
[root@master1 ~]# mysql_install_db --datadir=/data/mysql/ --user=mysql --force
[root@master2 ~]# mysql_install_db --datadir=/data/mysql/ --user=mysql --force

2、启动
[root@master1 ~]# /usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
[root@master2 ~]# /usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

3、权限
[root@master1 ~]# mysqladmin -S /data/mysql/mysql.sock -uroot -p password 'password'
Enter password:

[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password
复制权限
mysql> grant REPLICATION SLAVE on *.* to 'repl'@'192.168.11.%' identified by 'replpwd';
proxy权限
mysql> grant all on *.* to 'dbproxy'@'192.168.11.%' identified by 'dbproxypwd';

同样的操作在master2上执行一遍

五、同步

同步前再次确认网络连通情况
[root@master1 ~]# telnet 192.168.11.110 3306
[root@master2 ~]# telnet 192.168.11.100 3306
1、master1做主master2做从
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show master status;"
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 | 106 | | |
+------------------+----------+--------------+------------------+
mysql> change master to MASTER_HOST='192.168.11.100',MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='replpwd',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=106;
Query OK, 0 rows affected (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.11.100
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 106
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql,test,performance_schema
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 106
Relay_Log_Space: 406
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
1 row in set (0.00 sec)

2、master2做主master1做从
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show master status;"
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000005 | 106 | | |
+------------------+----------+--------------+------------------+

[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password
mysql> change master to MASTER_HOST='192.168.11.110',MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='replpwd',MASTER_LOG_FILE='mysql-bin.000005',MASTER_LOG_POS=106;
Query OK, 0 rows affected (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.11.110
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 106
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql,test,performance_schema
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 106
Relay_Log_Space: 406
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
1 row in set (0.00 sec)

六、测试
1、验证master1复制到master2
再master1创建库master1和表test_jin测试
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create database master1;"
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show databases;" |grep master1
master1
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create table master1.test_jin (id int(6) not null,name varchar(20) not null);"
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"use master1;show tables;"
+-------------------+
| Tables_in_master1 |
+-------------------+
| test_jin |
+-------------------+
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"insert into master1.test_jin values (100001,'kaijin');"
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master1.test_jin;"
+--------+--------+
| id | name |
+--------+--------+
| 100001 | kaijin |
+--------+--------

可见从master1复制到master2成功

2、验证master2复制到master1
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create database master2;"
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show databases;" |grep master2
master2

[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create table master2.test_master2 (id int(6) not null,name varchar(20) not null);"
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"use master2;show tables;"
+-------------------+
| Tables_in_master2 |
+-------------------+
| test_master2 |
+-------------------+

[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"insert into master2.test_master2 values (100002,'master2');"
[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master2.test_master2;"
+--------+---------+
| id | name |
+--------+---------+
| 100002 | master2 |
+--------+---------+

可见
验证master2复制到master1成功

双主相互复制成功

这里也解决了我一个疑问,创建库是否也复制。毫无疑问是复制的,只要记录在binglog里都会复制

七、总结
1、几个重点
1)log_slave_updates
log-slave-updates 默认未开启
log-slave-updates = 1开启
log-slave-updates是为从库的写操作记录binlog
在双主上必须配置。没有有它,双主是配不成的,关于它的详细介绍。在如下网址:
http://dev.mysql.com/doc/refman/5.1/en/replication-options-slave.html#option_mysqld_log-slave-updates
就是可以A -> B -> C,保证A可以作为master,复制到B,B可以作为master,复制到C.所以呢,如果A和B互相的话,就是双主了。
2)binlog_format
binlog_format = ROW
详细介绍binlog_format几种模式的区别,可以参考
http://codejm.iteye.com/blog/1540046

八、未测试部分
1、auto_increment 数据唯一性
测试可以参考:http://www.mysqlops.com/2011/06/07/mysql-replication-data-consistency.html

这里只往其中一个master写数据的保险的方法,如果要同时往两个master都写数据呢?
模拟出现的问题(多主自增长ID重复)
假如我们在master1,master2都建立一张test表,表中有一个auto increment的字段
停掉master1的同步,在master2上对数据表test(存在自增长ID)执行插入操作,返回插入ID为1
然后停掉master2的同步,在master1上对数据表test(存在自增长ID)执行插入操作,返回的插入ID也是1
然后同时启动master1,master2,就会出现主键ID重复

解决方法:
我们只要保证两台服务器上插入的自增长数据不同就可以了
master1增加配置
auto_increment_increment=2
auto_increment_offset=1

master2增加配置
auto_increment_increment=2
auto_increment_offset=2

具体
auto_increment_increment和auto_increment_offset用于主服务器-主服务器(master-to-master)复制
auto_increment_increment的默认值为1。
auto_increment_offset的默认值为1。

mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.01 sec)

auto_increment_offset确定AUTO_INCREMENT列值的起点。影响到在复制设置主可以有多少主服务器(例如将该值设置为10表示设置可以支持10个服务器)

第一个变量名 auto_increment_increment 就是指 字段一次递增多少;
第二个变量名 auto_increment_offset 指 自增字段的起始值。
比如,有个表test,字段id为主键,自增;
如果auto_increment_offset=1 , 并且auto_increment_increment=1,那么向表中插入第一条数据时,则该条数据的id=1,第二条id=2,第三条id=3以此类推……
如果auto_increment_offset=2 , 并且auto_increment_increment=10,那么向表中插入第一条数据时,则该条数据的id=2,第二条id=12,第三条id=22以此类推……
注意:如果auto_increment_offset的值大于auto_increment_increment的值,则auto_increment_offset的值被忽略。

在这里设置
auto_increment_increment=2
auto_increment_offset=1
第一条数据为1,第二条3,第三条5

auto_increment_increment=2
auto_increment_offset=2
第一条数据为2,第二条4,第三条6

2、read-only(保证只读)
在第二master上添加次参数
添加上测试一下
read-only默认未开启
read-only = 1 开启测试看看

[root@master2 ~]# kill $(cat /data/mysql/mysql.pid)
[root@master2 ~]#/usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
[root@master2 ~]# mysqladmin -S /data/mysql/mysql.sock --password=password VARIABLES |grep read_only
| read_only | ON

master2写入数据 看是否同步到master1
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"insert into master2.test_master2 values (100003,'master3');"
[root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master2.test_master2;"
+--------+---------+
| id | name |
+--------+---------+
| 100002 | master2 |
| 100003 | master3 |
+--------+---------+
可以写入master2

[root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master2.test_master2;"
+--------+---------+
| id | name |
+--------+---------+
| 100002 | master2 |
| 100003 | master3 |
+--------+---------+
也同步过去了
Cause the slave to permit no updates except from slave threads or from users having the SUPER privilege. On a slave server,
this can be useful to ensure that the slave accepts updates only from its master server and not from clients. This variable does not apply to TEMPORARY tables.
官方说明
导致从不允许任何更新,除了从从属线程或具有SUPER权限的用户。从服务器上的,这可能是有用的,以确保只从它的主服务器,而不是从客户的奴隶接受更新。此变量不适临时表。

这个参数不加也不要紧。要使用第二个主,也是在proxy里加入readonly

Mysql双主实战的更多相关文章

  1. 一个月后,我们又从 MySQL 双主切换成了主 - 从!

    这是悟空的第 157 篇原创文章 官网:www.passjava.cn 你好,我是悟空. 一.遇到的坑 一个月前,我们在测试环境部署了一套 MySQL 高可用架构,也就是 MySQL 双主 + Kee ...

  2. MySQL双主(主主)架构方案

    在企业中,数据库高可用一直是企业的重中之重,中小企业很多都是使用mysql主从方案,一主多从,读写分离等,但是单主存在单点故障,从库切换成主库需要作改动.因此,如果是双主或者多主,就会增加mysql入 ...

  3. 分布式数据存储 - MySQL双主复制

    上篇文章<分布式数据存储 - MySQL主从复制>,我们说到MySQL主从复制很好的保障了从库,读的高可用性.so,问题来了: 1.针对主库,写的高可用性又是如何做到高可用性? 2.如果需 ...

  4. MySQL双主配置

    MySQL双主配置 准备环境:服务器操作系统为RHEL6.4 x86_64,为最小化安装.主机A和主机B均关闭防火墙和SELINUX ,IP地址分别为192.168.131.129和192.168.1 ...

  5. Keepalived+MySQL双主

    一.Keepalived+MySQL Replication的应用场景 MySQL的高可用方案有cluster,MMM,MHA等,这些高可用方案都要三台服务器以上,成本有点高,今天介绍一个低成本高可用 ...

  6. keepalived+mysql双主复制高可用方案

    MySQL双主复制,即互为Master-Slave(只有一个Master提供写操作),可以实现数据库服务器的热备,但是一个Master宕机后不能实现动态切换.而Keepalived通过虚拟IP,实现了 ...

  7. MySQL集群(四)之keepalived实现mysql双主高可用

    前面大家介绍了主从.主主复制以及他们的中间件mysql-proxy的使用,这一篇给大家介绍的是keepalived的搭建与使用! 一.keepalived简介 1.1.keepalived介绍 Kee ...

  8. MYSQL 双主配置

    MYSQL1. 版本号:5.7.243. 部署方式:双主部署,两台机器即是主又是备 ,双向拷贝,可以同时写入.4. 安装部署路径: a) /home/softb) 配置路径 /etc/my.cnfc) ...

  9. MySql 双主多从配置指导

    MySql 双主多从配置指导 一.背景 互联网项目为了数据的可靠性和架构的可拓展性经常会用到双主多从的数据库,来实现数据的备份.负载均衡和突发状况时数据库切换. 二.思路 配置两台数据库A.B互为主从 ...

随机推荐

  1. C++之初始化问题

    首先,我们应该明确的是在C++中初始化不是赋值,因为初始化是必要的,如果读取了未初始化的值将会导致不明确的行为.初始化指创建变量并且给它赋初值,而赋值则是擦除对象的当前值并用新值代替.C++支持两种初 ...

  2. 在Linux中使用C语言实现控制流保护(CFG)【转】

    转自:http://www.codesec.net/view/537311.html 一.前言 最近版本的windows有一个新的缓解措施叫做控制流保护(CFG).在一个非直接调用之前――例如,函数指 ...

  3. 004 ConcurrentHashMap原理

    下面这部分内容转载自: http://www.haogongju.net/art/2350374 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为 ...

  4. HDU 5129 Yong Zheng's Death

    题目链接:HDU-5129 题目大意为给一堆字符串,问由任意两个字符串的前缀子串(注意断句)能组成多少种不同的字符串. 思路是先用总方案数减去重复的方案数. 考虑对于一个字符串S,如图,假设S1,S2 ...

  5. UIResponder简介

    1.简介 在使用设备的时候我们大多时候是但手指触摸控件了进行的,比如点击密码按钮解锁,上下浏览网页等动作.你肯定也摇动过iphone抢红包和***等等,我们的系统可以处理这些事件则都需要去使用UIRe ...

  6. 手机端调试console.log,直接引入一个js文件

    http://files.cnblogs.com/files/lwwen/mConsole.js 这是我写的一个原生js文件 直接引入即可,可以把html上面的需要打印的东西打印出来 <!DOC ...

  7. Django 项目CRM总结

    0. 项目说明: 1. 销售自动分配客户资源: 给销售分配权重及承单数量,创建权重表,通过销售权重进行从大到小进行排序 以承单数循环添加到列表,承单数是多少列表添加就添加多少次 考虑到如果服务重启,或 ...

  8. Jmeter+Jenkins持续集成(Ant运行脚本)

    Jmeter接口测试脚本运行后生成的是jtl(xml)格式的文件,这些文件不具备可读性,所以我们要把他转化为可以阅读的html格式报告. Ant是一个功能强大的打包编译工具.我们使用他的目的是将xml ...

  9. Nuget私服使用

    首先前提是师父已经搭好私服环境了(怎么搭建参考https://www.cnblogs.com/liupengblog/archive/2012/09/10/2678508.html). 然后在vs中打 ...

  10. CentOS7安装配置WPS

    1.下载 地址:http://wps-community.org/downloads 2.安装 rpm -ivh wps-office-10.1.0.5707-1.a21.x86_64.rpm 3.运 ...