> 数据库 > MySQL >

mysql双向同步设置及基本原理

1        背景介绍

学校内部有一台服务器(3g服务器),上面部署着uvge网站。在上海有一台服务器(上海服务器)。考虑到校外用户访问uvge网站时速度很慢,先决定在上海服务器上也部署个相同的网站,当外网用户想访问uvge网站时就访问上海服务器上的网站。

现在就需要解决一个问题:如何让校外用户浏览校内用户发表的帖子,校内用户也能浏览校外用户发表的帖子?

解决办法就是采用MySQL的双向同步技术

 

2        Mysql单向同步配置步骤

mysql的同步机制是基于日志的同步机制,所以主服务器一定要支持更改日志才行。然后设置要写入日志的数据库或者不要写入日志的数据库。这样只有您感兴趣的数据库的更改才写入到数据库的日志中。

前期准备:两台服务器上都已将网站部署好,两台服务器上的数据库也是一模一样。这里的数据库一摸一样是指所需要同步的表的内容一样,两个数据库的版本可以不一样。这里所做的是双向同步,所以两台服务器互为主从关系。

为了方便,上海服务器简称ucwise,学校服务器简称3g。

 

2.1      配置主数据库(ucwise)的my.ini文件

server-id=1 //数据库的id这个应该默认是1就不用改动
log-bin=log_name //日志文件的名称,这里可以制定日志到别的目录 如果没有设置则默认主机名的一个日志名称。
binlog-do-db=db_name //记录日志的数据库。
binlog-ignore-db=db_name //不记录日志的数据库。
以上的如果有多个数据库用","分割开。

auto-increment-offset=1 //表中第一条数据的编号(id)。

auto-increment-increment=2 //设置自动增量,向表中没添加一条数据,数据的id自动增2。这样就保证了主数据库中数据的id为1,3,5,7…..的形式。

2.2      为主库设置创建同步用户及赋权

先连接到主库中,

mysql> grant all privileges on *.* to'访问该数据库的用户名'@'可以访问该数据库的ip'identified by '访问该数据库用的密码'。;

mysql>flush privileges; 使生效

2.3      锁定数据库

mysql> flush tables with read lock;

这一步很重要,如果不锁定主数据库,那么其他用户还能对数据库里的数据进行写操作。一旦对主数据库进行了写操作,那么主从数据库里的内容就不一致了,在以后的同步过程中可能会出现错误。

2.4      配置从数据库(3g)的my.ini文件

在从数据库的my.ini文件中找到[mysqld]模块下,并添加一下内容:

server-id = 2

master-connect-retry =60    //从服务器发现主服务器断掉,重连时间差(秒)

replicate-do-db = testdb    //同步数据库:多个写多行

auto_increment_offset = 2 //表中第一条数据的id号

auto_increment_increment = 2//向表中每添加一条数据,id好自动增2.这就保证了该表中数据的id格式为:2,4,6,8….

这样主从库同步时就不会出现id号冲突了。

配置完毕保存后,增加了master.info与relay-log.info等文件。
停止MYSQL服务,删除data目录下除数据库外的所有文件, master.info和relay-log.info两文件必须删除。
注意:master修改my.ini时,master.info和relay-log.info必须删除重启服务。

2.5      查看主库状态

在主库上查看当前二进制日志名和偏移量值,注意:是查看主库

mysql> show master status;

记下返回结果中File属性的值和position的值,这两个值在以后的操作中会用的到。

注意:一旦主数据库的数据发生变化,这两个值就会随之发生改变。所以,如果主数据库中有数据写入,就要重新执行这个命令,获取最新的更新点。

2.6      在从数据库上制定更新点


先登录至从数据库,停止slave:

mysql> slave stop; //停止slave的服务

然后设置更新点:

mysql> CHANGE MASTERTO
    -> MASTER_HOST='主机ip',
    -> MASTER_USER='访问用户名',
    -> MASTER_PASSWORD='访问密码',
    -> MASTER_LOG_FILE='mysql-bin.000008',
    -> MASTER_LOG_POS=880;
Query OK, 0 rows affected (0.01 sec)
注意到这里master_log_file和master_log_pos就是前面show master status的结果。

2.7      查看从数据库状态

登录从数据库,在数据库中输入以下命令:

mysql> show slave status\g;

 

返回结果中如果没有错误信息就表示,主从数据库都已经配置连接好,可以进行同步了。

2.8      启动同步线程

mysql> slave start;

2.9      解除主库锁定

mysql> unlock tables;

现在可以对主数据库进行写操作了,所有在主数据库中进行的写操作在从数据库中都会有相同的操作。单向同步完成。

3        双向同步配置

我们在前面已经实现了单向同步,ucwis服务器中数据库为主数据库,3g服务器中数据库为从数据库。反过来,我们在把3g服务器中的数据库作为主数据库,把ucwise服务器中的数据库作为从数据库,就可以实现反向同步,这样一来,双向同步就实现了。所以,要实现双向同步,我们只需在原有的操作中添加以下操作:

3.1      查看从库状态

 

在从数据库上查看当前二进制日志名和偏移量值,注意:是查看从库

mysql>show master status;

 

3.2      在主数据库中设置更新点

在主服务器上指定更新点(根据上面查的记录)

mysql>CHANGE MASTER TO

    -> MASTER_HOST='从数据库ip',

    -> MASTER_PORT=3306,

    -> MASTER_USER='登录用户',

    -> MASTER_PASSWORD='访问密码',

    -> MASTER_LOG_FILE='mysql-bin.000009',

    -> MASTER_LOG_POS=990;

3.3      在数据库中启动同步线程

登录主数据库,输入以下命令,启动同步线程,就可以开始双向同步。

mysql> slave stop;

mysql> slave start;

注意:本次测试主从数据库的版本都是mysql5.5。如果数据库的版本低于5.1.7,那么配置文件中可以直接设置master参数。

4        主从同步原理

4.1      日志文件的作用

主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。

MySQL复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新、删除等等)。因此,要进行复制,必须在主服务器上启用二进制日志。

每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新,以便从服务器可以对其数据拷贝执行相同的更新。

从服务器设置为复制主服务器的数据后,它连接主服务器并等待更新过程。如果主服务器失败,或者从服务器失去与主服务器之间的连接,从服务器保持定期尝试连接,直到它能够继续帧听更新。由--master-connect-retry选项控制重试间隔。 默认为60秒。

每个从服务器跟踪复制时间。主服务器不知道有多少个从服务器或在某一时刻有哪些被更新了。

 

4.2      主从同步过程的相关文件

默认情况,中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机名,nnnnnn是序 列号。用连续序列号来创建连续中继日志文件,从000001开始。从服务器跟踪索引文件中目前正使用的中继日志。 默认中继日志索引文件名为host_name-relay-bin.index。默认情况,在从服务器的数据目录中创建这些文件。可以用--relay- log--relay-log-index服务器选项覆盖 默认文件名

中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。SQL线程执行完中继日志中的所有事件并且不再需要之后,立即自动删除它。没有 直接的删除中继日志的机制,因为SQL线程可以负责完成。然而,FLUSH LOGS可以循环中继日志,当SQL线程删除日志时会有影响。

 

从属复制服务器在数据目录中另外创建两个小文件。这些状态文件默认名为主master.info和relay-log.info。它们包含SHOW SLAVE STATUS语句的输出所显示的信息(关于该语句的描述参见13.6.2节,“用于控制从服务器的SQL语句”)。状态文件保存在硬盘上,从服务器关闭时 不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。

由I/O线程更新master.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:

 

 

行 描述

1 文件中的行号

2 Master_Log_File

3 Read_Master_Log_Pos

4 Master_Host

5 Master_User

6 密码(不由SHOW SLAVE STATUS显示)

7 Master_Port

8 Connect_Retry

9 Master_SSL_Allowed

10 Master_SSL_CA_File

11 Master_SSL_CA_Path

12 Master_SSL_Cert

13 Master_SSL_Cipher

14 Master_SSL_Key

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


由SQL线程更新relay-log.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:

 

 

行 描述

1 Relay_Log_File

2 Relay_Log_Pos

3 Relay_Master_Log_File

4 Exec_Master_Log_Pos

 

 

 

 

 

 

 

 

 


4.3    主从同步过程的相关文件和MySQL语句的关系

 

 

行 描述

1 文件中的行号

2 Master_Log_File

3 Read_Master_Log_Pos

4 Master_Host

5 Master_User

6 密码(不由SHOW SLAVE STATUS显示)

7 Master_Port

8 Connect_Retry

9 Master_SSL_Allowed

10 Master_SSL_CA_File

11 Master_SSL_CA_Path

12 Master_SSL_Cert

13 Master_SSL_Cipher

14 Master_SSL_Key

由I/O线程更新master.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SQL线程更新relay-log.info文件。文件中的行和SHOW SLAVE STATUS显示的列的对应关系为:

 

 

行 描述

1 Relay_Log_File

2 Relay_Log_Pos

3 Relay_Master_Log_File

4 Exec_Master_Log_Pos

 

 


 

 

 

 

 

 

 

当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继续进行复制。如果丢失了中继日志但仍然有 relay-log.info文件,你可以通过检查该文件来确定SQL线程已经执行的主服务器中二进制日志的程度。然后可以用 Master_Log_File和Master_LOG_POS选项执行CHANGE MASTER TO来告诉从服务器重新从该点读取二进制日志。当然,要求二进制日志仍然在主服务器上。

如果从服务器正复制LOAD DATAINFILE语句,你应也备份该目录内从服务器用于该目的的任何SQL_LOAD-*文件。从服务器需要这些文件继续复制任何中断的LOAD DATA INFILE操作。用--slave-load-tmpdir选项来指定目录的位置。如果未指定,默认值为tmpdir变量的值。

4.4      主从同步起点的说明

master.info的内容会覆盖命令行或in my.cnf中指定的部分选项。如果从服务器启动时master.info文件不存在,选项采用选项文件或命令行中指定的值。首次将服务器作为从服务器启动时,或者已经运行RESET SLAVE然后已经关闭并重启从服务器时会发生。

如果从服务器启动时master.info文件存在,服务器忽略那些选项。使用master.info文件中发现的值。如果你使用与master.info文件中相对应的启动选项的不同的值重启从服务器,启动选项的不同的值不会生效,因为服务器继续使用 master.info文件。要想使用启动选项的不同的值,必须删除master.info文件并重启从服务器,或(最好是)在从服务器运行时使用 CHANGEMASTER TO语句重新设置值。

4.5    两个重要的选项

· --logs-slave-updates

这个是在my.cnf文件配置的。通常情况,从服务器从主服务器接收到的更新不记入它的二进制日志。该选项告诉从服务器将其SQL线程执行的更新记入到从服务器自己的二进制日志。为了使该 选项生效,还必须用--logs-bin选项启动从服务器以启用二进制日志。

如果想要应用链式复制服务器,应使用logs-slave-updates。例如,可能你想要这样设置:A -> B -> C 也就是说,A为从服务器B的主服务器,B为从服务器C的主服务器。为了能工作,B必须既为主服务器又为从服务器。你必须用--logs-bin启动A和B以启用二进制日志,并且用--logs-slave-updates选项启动B。

·--slave-skip-errors=[err_code1,err_code2,... | all]

这个是在mysql启动时的选项通常情况,当出现错误时复制停止,这样给你一个机会手动解决数据中的不一致性问题。该选项告诉从服务器SQL线程当语句返回任何选项值中所列的错误时继续复制。

如果你不能完全理解为什么发生错误,则不要使用该选项。如果复制设置和客户程序中没有bug,并且MySQL自身也没有bug,应不会发生停止复制的错误。滥用该选项会使从服务器与主服务器不能保存同步,并且你找不到原因。

对于错误代码,你应使用从服务器错误日志中错误消息提供的编号和SHOW SLAVE STATUS的输出。服务器错误代码列于附录B:错误代码和消息。

你也可以(但不应)使用不推荐的all值忽略所有错误消息,不考虑所发生的错误。无需而言,如果使用该值,我们不能保证数据的完整性。在这种情况下,如果从服务器的数据与主服务器上的不相近请不要抱怨(或编写bug报告),已经警告你了。



(责任编辑:IT)