mysql复制策略

架构变化的同时,业务也在不断的发展,可能很快就会发现,随着访问量的不断增加,拆分后的某个数据库压力越来越大,马上就要达到能力的瓶颈,数据库的架构不得不再次进行变更,这时通过mysql的复制策略来对系统进行扩展。
通过数据库的复制策略,可以将一台mysql数据库服务器中的数据复制到其他的mysql数据库服务器上。当各台数据库服务器上都包含相同数据时,前端应用通过访问mysql集群中任意一台服务器,都能够读到相同的数据,这样每台mysql服务器所需要承担的负载就会大大降低。从而提高整个系统的承载能力,达到系统扩展的目的。

master-slave复制策略

要实现数据库的复制,需要开启Master服务端的Binary log。数据复制的过程实际上就是Slave从Master上获取Binary log的过程,然后再在本地镜像的执行日志中记录的操作。由于复制过程是异步的,因此Master和Slave之间的数据有可能存在延迟的现象,此时只能够保证数据最终的一致性。

主从复制原理

整体上来说,复制有3个步骤:

(1)master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
(2)slave将master的binary log events拷贝到它的中继日志(relay log);
(3)slave重做中继日志中的事件,将改变反映它自己的数据。


Mysql的复制可以基于一条语句(statement Level),也可以基于一条记录(row level)。通过row level的复制,可以不记录执行的sql语句相关联的上下文信息,只需要记录数据变更的内容即可。但由于每行的变更都会被记录,这样可能会产生大量的日志内容,而使用statement level在只是记录修改数据的sql语句,减少binary log的日志量,节约了I/O成本。但是,为了让sql语句在Slave也能正确的执行,它还需要记录sql执行的上下文信息,以保证所有sql语句在Slave执行时能够得到在Master端执行的相同的结果。

mysql的master-slaves配置

环境说明

数据库:mysql 5.5
系统:CentOS 6.5
在每台机器上面安装mysql 5.5的服务端和客户端

配置

一般主从搭建的步骤如下:

1、创建主库、从库
2、dump主库数据到从库
3、修改主库、从库配置
4、主库grant user,从库start slave

Master配置

在[mysqld]下面添加如下配置信息:

server-id     =   1           # 服务ID
log-bin       =   mysql-bin   # 开启二进制日志(见附录)
binlog-do-db  =   test        # 需要同步的数据库
binlog-ignore-db=mysql        # 被忽略的数据库
binlog-ignore-db=information-schema # 被忽略的数据库

为slave添加登陆master的账号:

mysql> grant replication slave,replication client on *.* to '账号'@'从服务器IP地址' identified by '密码';

保存后重启mysql服务,service mysql restart,然后进入mysql命令行查看master状态:

mysql> show master status\G;
**************** 1. row ****************
File: mysql-bin.000001
Position: 106
Binlog_Do_DB: test
Binlog_Ignore_DB: mysql,information-schema
1 row in set (0.00 sec)

可以查看到File为mysql-bin.000001;Position为106,这在后面slave数据还原有作用!

Slave配置

在[mysqld]下面添加如下配置信息:

server-id = 2        # 服务ID
replicate-do-db=test # 同步数据库
replicate-ignore-db=mysql # 被忽略的数据库
replicate-ignore-db=infomation-schema # 被忽略的数据库

在5.1之后废弃了如下的写法:

master-host=192.168.1.199
master-user= slave1
master-password=slave1    
master-port=3306

使用如下的写法:

change master to master_host='192.168.83.61', master_user='slave1', master_password='slave1';

如果需要先使用mysqldump导出数据,想从master的指定位置还原的话,就要先锁定master数据库,导入sql,然后使用如下的命令,并填入master服务器二进制索引文件的名称和pos值:

change master to master_host='192.168.83.61',master_post=3306,master_user='slave1', master_password='slave1',master_log_file='mysql-bin.000001',master_log_pos=106;

这样就可以启动从服务器,并查看状态

start slave;
show slave status\G;

如果查看显示一下两个变量都是yes表示主从运行正常

Slave_IO_Running:连接到主库,并读取主库的日志到本地,生成本地日志文件
Slave_SQL_Running:读取本地日志文件,并执行日志里的SQL命令。

接下来就可在主数据库更新数据然后就可以在从库中查看数据是否同步成功

使用mysqldump来备份和还原数据

# 先锁表,然后备份,还原,解锁表

# mysqldump备份
mysqldump -u用户名 -p密码 -h主机 数据库名 > 导出路径
mysqldump -uroot -p123456 -hlocalhost test > /home/mysql/test.sql
mysqldump -u用户名 -p密码 -h主机 数据库名 表名 > 导出路径

## 导出一个数据库结构
mysqldump -u用户名 -p密码 -h主机 数据库名 --no-data --add-drop-database --add-drop-table smgp_apps_wcnc > 导出路径 
### --no-data:不dump数据库的数据,--add-drop-database:创建数据库之前加一个drop database;--add-drop-table 在每个create语句之前增加一个drop table 

# 还原数据库
## 未进入数据库
mysql -u用户名 -p密码 -h主机 < /home/mysql/test.sql
mysqldump -u用户名 -p密码 -h主机 数据库名 < 导入路径
## 进入数据库
source /home/mysql/test.sql

master-master复制策略

Master-Slaves复制架构存在一个问题,即所谓的单节点故障。当Master宕机时,系统将无法写入,而在某些特定的场景下,也可能需要Master停机,以便进行系统维护,优化或者升级。同样的道理,Master体积将会导致整个系统都无法写入,知道Master恢复,大部分情况下这显然是难以接受的,为了尽可能低系统停止写入的时间,最佳的方式就是Dual-Master架构,即Master-Master架构。

创建同步用户

master1上:

grant replication slave,replication client on *.* to '账号'@'master2IP' identified by '密码';

master2上;

grant replication slave,replication client on *.* to '账号'@'master1IP' identified by '密码';

使用select host,user from mysql.user来查询同步用户是否创建成功!

修改配置文件

master1配置文件如下:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id=1
log-bin = mysql_bin
port=3306

#master-maser need add
log-slave-updates
sync_binlog=1
auto_increment_offset=1
auto_increment_increment=2
#replicate-do-db = test
#replicate-ignore-db = mysql,information_schema

master2配置文件如下:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
innodb_file_per_table
server-id=2
#relay-log-purge=1
read-only=1 # 0 read/write 1 read only.
log-bin

#master-master need add
#binlog-do-db = test
#binlog-ignore-db=mysql
log-slave-updates
sync_binlog=1
auto_increment_offset=2
auto_increment_increment=2

重启服务器上面的mysql server服务器

查看服务器状态

master1查看服务器状态:

mysql>flush tables with read lock;
mysql> show master status;
+------------------------+----------+--------------+------------------+-------------------+
| File                   | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------------+----------+--------------+------------------+-------------------+
| mysqlmaster-bin.000001 |      128 |              |                  |                   |
+------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql>unlock tables;

master2查看服务器状态:

mysql>flush tables with read lock;
mysql> show master status;
+-----------------------+----------+--------------+------------------+-------------------+
| File                  | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------------+----------+--------------+------------------+-------------------+
| mysqlslave-bin.000001 |      334 |              |                  |                   |
+-----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql>unlock tables;

注:
这里锁表和解锁的目的是为了生产环境中不让进新的数据,好让从服务器定位同步位置。
如果主数据库本来就有数据的情况下,在锁表之后还需要备份主服务器的数据库,再恢复到从服务器的过程,使主从数据库数据一致,再做复制。
由于我们是新安装的数据库,主从服务器的数据是一致的,因此可忽略锁表、备份恢复、解锁等步骤。

指定同步位置

master1设置同步位置:

change master to master_host='192.168.1.200',master_user='xiaoyu', master_password='xiaode',master_log_file='mysql-bin.000002',master_log_pos=107;

master2设置同步位置:

change master to master_host='192.168.1.177',master_user='xiaoyu', master_password='xiaode',master_log_file='mysql-bin.000001',master_log_pos=364;

启动从服务器进程

master1启动并查看状态:

mysql> start slave;
mysql> show slave status\G;

master2启动并查看状态:

mysql> start slave;
mysql> show slave status\G;

查看进程状态:

mysql> show processlist\G;

Dual-Master同步测试

如果分别从两个数据上面增删改都可以同步,两边数据一致的话,说明Dual-Master同步配置成功!

附录

log_bin日志

my.conf文件中的[mysqld]标签下的log_bin指定日志文件,如果不提供文件名,mysql将自己产生缺省文件名。mysql会在文件名后面自动添加数字引,每次启动服务时,都会重新生成一个新的二进制文件。

此外,使用log-bin-index可以指定索引文件;
使用binlog-do-db可以指定记录的数据库;
使用binlog-ignore-db可以指定不记录的数据库。

注意的是:binlog-do-db和binlog-ignore-db一次只指定一个数据库,指定多个数据库需要多个语句。
而且,MySQL会将所有的数据库名称改成小写,在指定数据库时必须全部使用小写名字,否则不会起作用。

以后对数据库每做的一次操作,都会在binlog中有所记录。

master-master架构主键冲突

如果数据库id需要自增长的话,且业务要求id可以不连续的话,可以设置如下的两个参数,保证一个数据库是奇数增长,一个数据库是偶数增长,这样两者就不会出现主键冲突的问题了

1auto-increment-increment=2 
auto-increment-offset=12auto-increment-increment=2 
auto-increment-offset=2

参考

MySQL主从复制原理以及架构
MySQL 5.5.40实现一主多从 One-Master muil-slave
MySQL Dual Master环境配置(一)
MySQL Dual Master环境配置(二)