mysql主从原理

 

复制通常用来创建主节点的副本,通过添加冗余节点来保证高可用性,当然复制也可以用于其他用途,例如在从节点上进行数据读、分析等等。在横向扩展的业务中,复制很容易实施,主要表现在在利用主节点进行写操作,多个从节点进行读操作,mysql复制的异步性是指:事物首先在主节点上提交,然后复制给从节点并在从节点上应用,这样意味着在同一个时间点主从上的数据可能不一致,异步复制的好处在于它比同步复制要快,如果对数据的一致性要求很高,还是采用同步复制较好。

最简单的复制模式就是一主一从的复制模式了,这样一个简单的架构只需要三个步骤即可完成:

1 建立一个主节点,开启binlog,设置服务器id

2 建立一个从节点,设置服务器id

3 将从节点连接到主节点上

下面我们开始操作,以mysql5.5为例,操作系统ubuntu12.10,master 10.1.6.159 slave 10.1.6.191

?

1 apt-get install mysql-server

 

master机器

master上面开启binlog日志,并且设置一个唯一的服务器id,在局域网内这个id必须唯一。二进制的binlog日志记录master上的所有数据库改变,这个日志会被复制到从节点上,并且在从节点上回放。修改my.cnf文件,在mysqld模块下修改如下内容:

?

1

2

3

[mysqld]

server-id   = 1

log_bin     = /var/log/mysql/mysql-bin.log

log_bin设置二进制日志所产生文件的基本名称,二进制日志由一系列文件组成,log_bin的值是可选项,如果没有为log_bin设置值,则默认值是:主机名-bin。如果随便修改主机名,则binlog日志的名称也会被改变的。server-id是用来唯一标识一个服务器的,每个服务器的server-id都不一样。这样slave连接到master后,会请求master将所有的binlog传递给它,然后将这些binlog在slave上回放。为了防止权限混乱,一般都是建立一个单独用于复制的账户。

?

1

2

create user rep;

grant replication slave on *.* to rep identified by '123456';

binlog是复制过程的关键,它记录了数据库的所有改变,通常即将执行完毕的语句会在binlog日志的末尾写入一条记录,binlog只记录改变数据库的语句,对于不改变数据库的语句则不进行记录。这种情况叫做基于语句的复制,还有一种情况是基于行的复制,两种模式各有各的优缺点。

 

slave机器

slave机器和master一样,需要一个唯一的server-id

?

1

2

[mysqld]

server-id   = 2

 

连接slave到master

在master和slave都已经配置好后,只需要把slave指向master即可

?

1

2

change master to master_host='10.1.6.159',master_port=3306,master_user='rep',master_password='123456';

start slave;

接下来在master上做一些针对改变数据库的操作,来观察slave的变化情况。在修改完my.cnf配置重启数据库后,就开始记录binlog了。可以在/var/log/mysql目录下看到一个mysql-bin.000001文件,而且还有一个mysql-bin.index文件,这个mysql-bin.index文件是什么?这个文件保存了所有的binlog文件列表,但是我们在配置文件中并没有设置改值,这个可以通过log_bin_index进行设置,如果没有设置改值,则默认值和log_bin一样。在master上执行show binlog events命令,可以看到第一个binlog文件的内容。

注意:上面的sql语句是从头开始复制第一个binlog,如果想从某个位置开始复制binlog,就需要在change master to时指定要开始的binlog文件名和语句在文件中的起点位置,参数如下:master_log_file和master_log_pos。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

mysql> show binlog events\G

*************************** 1. row ***************************

Log_name: mysql-bin.000001

Pos: 4

Event_type: Format_desc

Server_id: 1

End_log_pos: 107

Info: Server ver: 5.5.28-0ubuntu0.12.10.2-log, Binlog ver: 4

*************************** 2. row ***************************

Log_name: mysql-bin.000001

Pos: 107

Event_type: Query

Server_id: 1

End_log_pos: 181

Info: create user rep

*************************** 3. row ***************************

Log_name: mysql-bin.000001

Pos: 181

Event_type: Query

Server_id: 1

End_log_pos: 316

Info: grant replication slave on *.* to rep identified by '123456'

3 rows in set (0.00 sec)

Log_name 是二进制日志文件的名称,一个事件不能横跨两个文件

Pos 这是该事件在文件中的开始位置

Event_type 事件的类型,事件类型是给slave传递信息的基本方法,每个新的binlog都已Format_desc类型开始,以Rotate类型结束

Server_id 创建该事件的服务器id

End_log_pos 该事件的结束位置,也是下一个事件的开始位置,因此事件范围为Pos~End_log_pos-1

Info 事件信息的可读文本,不同的事件有不同的信息

 

在master的test库中创建一个rep表,并插入一条记录。

?

1

2

3

create table rep(name var);

insert into rep values ("guol");

flush logs;

flush logs命令强制轮转日志,生成一个新的二进制日志,可以通过show binlog events in 'xxx'来查看该二进制日志。可以通过show master status查看当前正在写入的binlog文件。这样就会在slave上执行相应的改变操作。

上面就是最简单的主从复制模式,不过有时候随着时间的推进,binlog会变得非常庞大,如果新增加一台slave,从头开始复制master的binlog文件是非常耗时的,所以我们可以从一个指定的位置开始复制binlog日志,可以通过其他方法把以前的binlog文件进行快速复制,例如copy物理文件。在change master to中有两个参数可以实现该功能,master_log_file和master_log_pos,通过这两个参数指定binlog文件及其位置。我们可以从master上复制也可以从slave上复制,假如我们是从master上复制,具体操作过程如下:

1 为了防止在操作过程中数据更新,导致数据不一致,所以需要先刷新数据并锁定数据库:flush tables with read lock

2 检查当前的binlog文件及其位置:show master status

?

1

2

3

4

5

6

7

mysql> show master status\G

*************************** 1. row ***************************

File: mysql-bin.000003

Position: 107

Binlog_Do_DB:

Binlog_Ignore_DB:

1 row in set (0.00 sec)

3 通过mysqldump命令创建数据库的逻辑备分:mysqldump --all-databases -hlocalhost -p >back.sql

 

4 有了master的逻辑备份后,对数据库进行解锁:unlock tables

5 把back.sql复制到新的slave上,执行:mysql -hlocalhost -p <back.sql把master的逻辑备份插入slave的数据库中

6 现在可以把新的slave连接到master上了,只需要在change master to中多设置两个参数master_log_file='mysql-bin.000003'和master_log_pos='107'即可,然后启动slave:start slave,这样slave就可以接着107的位置进行复制了。

 

有时候master并不能让你锁住表进行复制,因为可能跑一些不间断的服务,如果这时master已经有了一个slave,我们则可以通过这个slave进行再次扩展一个新的slave。原理同在master上进行复制差不多,关键在于找到binlog的位置,你在复制的同时可能该slave也在和master进行同步,操作如下:

1 为了防止数据变动,还是需要停止slave的同步:stop slave

2 然后刷新表,并用mysqldump逻辑备份数据库

3 使用show slave status查看slave的相关信息,记录下两个字段的值Relay_Master_Log_File和Exec_Master_Log_Pos,这个用来确定从后面哪里开始复制。

4 对slave解锁,把备份的逻辑数据库导入新的slave的数据库中,然后设置change master to,这一步和复制master一样。

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code