Mysql主从复制原理

原创
2013/01/05 20:57
阅读数 6.1K

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

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

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

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

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

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

apt-get install mysql-server


master机器

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

[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上回放。为了防止权限混乱,一般都是建立一个单独用于复制的账户。

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


slave机器

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

[mysqld]
server-id	= 2


连接slave到master

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

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。

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表,并插入一条记录。

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

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一样。


展开阅读全文
打赏
0
34 收藏
分享
加载中
更多评论
打赏
0 评论
34 收藏
0
分享
返回顶部
顶部