mysql复制

实验环境:rhel6.5      mysql-5.1.71

master              server1.example.com 172.25.12.1

slave1              server2.example.com 172.25.12.2

slave2              server3.example.com 172.25.12.3

拓扑图:

原理:

1、MySQL Replication复制进程

MySQL的复制(replication)是一个异步的复制,从一个MySQL instace(称之为Master)复制到另一个MySQL instance(称之Slave)。实现整个复制操作主要由三个进程完成的,其中两个进程在Slave(Sql进程和IO进程),另外一个进程在Master(IO进程)上。

要实施复制,首先必须打开Master端的binary log(bin-log)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。

2,MySQL Replication复制的基本过程如下:

1)、Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

2)、Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;

3)、Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的高速Master"我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我";

4)、Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。

决了性能问题,又缩短了异步的延时时间,同时也减少了可能存在的数据丢失量。当然,即使是换成了现在这样两个线程处理以后,同样也还是存在slave数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事物中,这些问题都是会存在的。如果要完全避免这些问题,就只能用MySQL的cluster来解决了。不过MySQL的cluster是内存数据库的解决方案,需要将所有数据都load到内存中,这样就对内存的要求就非常大了,对于一般的应用来说可实施性不是太大。

MySQL Replication复制实现级别
参考:mysql性能调优与架构设计

MySQL Replication复制可以是基于一条语句(Statement level)上下文,效率高。也可以是基于一条记录(Row level)。记录日志太多,但易解析。

(1)Row Level

Binary Log会记录成每一行数据被修改的形式,然后在Slave端再对相同的数据进行修改。

优点:在Row Level模式下,Binary Log可以不记录执行的Query语句的上下文相关信息,只需要记录哪一条记录被修改了,修改成什么样了。所以 Row Level的日志内容会非常清楚地记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程,或 function,以及 Trigger的调用和触发无法正确复制的问题。

缺点:在Row Level模式下,当所有的执行语句记录到Binary Log 中时,都将被记录成每条记录被修改的形式,这样就会产生大量的日志内容。比如有这样的一条 update语句:UPDATE group_message SET group_id = 1 WHERE group_id=2,执行后,日志记录的不是该语句而是产生影响的 表中的每条记录,即:如果group_message 中有 group_id=1 的记录100条,那么Binary Log中记录了这100条记录的变化情况。尤其执行 Alter Table 之类的语句时,产生的日志量更大的惊人。因为MYSQL对于Alter Table之类的DDL变更语句是重建整个表的所有数据,即表中每一条记录都要变动,那么该表中所有记录都要记录到日志中。

(2)Statement Level

每一条会修改数据的Query都会记录到Master的Binary Log中以及执行语句时上下文的信息。Slave 在复制的时候,SQL线程会解析成和原来 Master 端执行过的相同的 Query,并再次执行。

有点:首先解决了Row Level的缺点,不需要记录每一行记录的变化,减少了Binary Log 日志量,节约了IO成本,提高了性能。

缺点:由于记录的是执行语句,为了能让这些语句在Slave端也能正确执行,就需要记录每条语句在执行时的一些相关信息,即上下文信息。另外由于MYSQL发展比较快,很多新功能的加入,也使得mysql复制遇到不少挑战,复制时涉及的内容越复杂越容易出现bug。在修改数据时使用了默写特定的函数或功能后会出现问题。如 sleep()函数在默写版本中不能正确复制,在存储过程中使用 last_insert_id()函数,可能会使Slave 和Master得到不一致的ID,由于Row Level是基于每一行变化的所以不会出现这种情况。

(3) Mixed Level

在Mixed模式下,mysql会根据执行的每一条具体的Query语句来区分对待记录的日志形式,也就是在 Statement和Row之间选择一种。从5.1.8版本开始,Mysql提供了Statement Level 和 Row Level之外的第三种复制模式 Mixed Level

需要注意的是在复制时,Master和slave的日志格式一定要一样哦,因为mysql不会自动的转换,所以就会出错row form 。不过在5.1之前是没有这类问题的,因为都是statement语句。建议修改binlog-form的使用都在各自上的都同步上。

作用:

单向复制有利于健壮性、速度和系统管理:

1. 主服务器/从服务器设置增加了健壮性。主服务器出现问题时,你可以切换到从服务器作为备份

2. 通过在主服务器和从服务器之间切分处理客户查询的负荷,可以得到更好的客户响应时间。SELECT 查询可以发送到从服务器以降低主服务器的查询处理负荷。但修改

数据的语句仍然应发送到主服务器,以便主服务器和从服务器保持同步。如果非更新查询为主,该负载均衡策略很有效,但一般是更新查询。

3. 使用复制的另一个好处是可以使用一个从服务器执行备份,而不会干扰主服务器。在备份过程中主服务器可以继续处理更新。

MySQL 提供了数据库的同步功能,这对我们实现数据库的冗灾、备份、恢复、负载均衡等都是有极大帮助的。

mysql的AB复制

在主从节点上安装mysql

yum install mysql-server -y

1) master:

配置 /etc/my.cnf 配置文件

log-bin=mysql-bin #启动二进制日志系统

binlog-do-db=test #二进制需要同步的数据库名,需要同步多个库,另写一行,名称变就行

server-id=1        #必须为 1 到 232–1 之间的一个正整数值

#每一个同步中的slave在master上都对应一个master线程,该线程就是通过slave的server-id来标识的;每个slave在master端最多有一个master线程,如果两个slave的server-id 相同,则后一个连接成功时,前一个将被踢掉.如果slave start 起不来.可能就是server-id的原因.改变id的值.重起服务就好.

binlog-ignore-db=mysql #禁止同步 mysql 数据库

启动服务;授权给slave

mysql> grant replication slave on *.* to redhat@'172.25.12.%' identified by 'redhat';

mysql> flush privileges;

在slave端测试.是否能等上数据库

[root@server2 ~]# mysql -uredhat -predhat -h 172.25.12.1

为了保证主备数据的一致性,应先把主的数据备份到备的上面去。

先锁表,保证数据的一致性:flush tables with read lock;

全备: mysqldump -predhat --all-databases > all_dump.sql

查看master 状态

mysql> show master status;

+------------------+----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000004 | 346 | test | mysql |

+------------------+----------+--------------+------------------+

1 row in set (0.00 sec)

记录 File 和 Position 的值,下面会用到

解锁 unlock tables

2)salver的配置

配置 /etc/ my.cnf 文件

在[mysqld]下添加一下参数

server-id=2

一些其他的选项:

master-connect-retry        当与主库断开,重新连接的间隔时间

read-only     拒绝普通用户的更新操作,以确保从库的安全性

连接主库

mysql> change master to

-> master_host='192.168.88.121',

-> master_user='rep',

-> master_password='redhat',

-> master_log_file='mysql-bin.000002',

-> master_log_pos=0;

检测参数设值是否正确:show slave statusG;

启动;连接master

注意logfile和postion都上上面master的信息,当然position可以从0开始

mysql> slave start;

Query OK, 0 rows affected (0.00 sec)

mysql> show slave statusG;

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

Slave_IO_State: Waiting for master to send event

Master_Host: 172.25.12.1

Master_User: redhat

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000004

Read_Master_Log_Pos: 346

Relay_Log_File: mysqld-relay-bin.000002

Relay_Log_Pos: 251

Relay_Master_Log_File: mysql-bin.000004

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

分别在主备上执行show processlist;查看复制的进度、状态。

主库:mysql> show processlistG;

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

Id: 12

User: rep

Host: server2.example.com:39764

db: NULL

Command: Binlog Dump

Time: 2513

State: Has sent all binlog to slave; waiting for binlog to be updated

Info: NULL

从库:mysql> show processlistG;

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

Id: 4

User: system user

Host:

db: NULL

Command: Connect

Time: 2443                ###自上次主服务器更新,最后执行复制操作到现在的时间

State: Waiting for master to send event

Info: NULL

当Slave_IO_Running、Slave_SQL_Running两项都是Yes时,一般都表示复制成功了,通常IO不正常时,一般是网络、火墙、设置主库节点信息等问题,SQL不正常,主备两节点数据库的结构可能不一致的问题

另外在复制的过程中,由于各种原因,从服务器可能会遇到binlog中的sql出错的情况(比如主键冲突)。默认情况下,从服务器会停止复制进程,不再进行同步,等待用户的介入。如果备库主要用于分担数据库的查询压力,且对数据的完整性要求不高,那么可以在备库加上slave-skip-errors的参数,用于跳过错误,继续执行复制。如果是作为主库的备份则,不应当设定这个参数

在master插入数据看slave上否同步

master:

mysql> use test;

Database changed

mysql> create table user (

-> name varchar(20) not null,

-> pass varchar(20) not null

-> );

Query OK, 0 rows affected (0.03 sec)

mysql> insert into user values('wang','redhat');

Query OK, 1 row affected (0.00 sec)

slave:

mysql> select * from user;

+------+--------+

| name | pass |

+------+--------+

| wang | redhat |

+------+--------+

级联复制架构 Master –Slaves - Slaves

在有些应用场景中,可能读写压力差别比较大,读压力特别的大,一个Master可能需要上10台甚至更多的Slave才能够支撑注读的压力。这时候,Master就会比较吃力了,因为仅仅连上来的SlaveIO线程就比较多了,这样写的压力稍微大一点的时候,Master端因为复制就会消耗较多的资源,很容易造成复制的延时。这时候我们就可以利用MySQL可以在Slave端记录复制所产生变更的BinaryLog信息的功能,也就是打开log_slave_update选项。然后,通过二级(或者是更多级别)复制来减少Master端因为复制所带来的压力。

这种多层级联复制的架构,很容易就解决了Master端因为附属Slave太多而成为瓶颈的风险。

但下面阶级过多.同一个变更传到最底层的Slave所需要经过的MySQL也会更多,同样可能造成延时较长的风险

拓扑图:

原理图

添加slave2.(server3.example.com)

配置slave1

vim /etc/my.cnf

server-id=2

log-bin=mysql-bin

binlog-do-db=test

binlog-ignore-db=mysql

log-slave-update

重启mysql

给slave2.配置

添加id就好 server-id=3

由于 master 上已经有数据,而新加的 slave2 没有,必须在配置复制前同步数据。

mysqlbinlog --start-position=346 --stop-position=588 mysql-bin.000004 | mysql (要注意看始末位置)

启动服务;授权给slave2

mysql> grant replication slave,reload,super on *.* to redhat@'172.25.12.%' identified by 'redhat';

mysql> flush privileges;

mysql> show master status;

+------------------+----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000001 | 346 | test | mysql |

+------------------+----------+--------------+------------------+

1 row in set (0.00 sec)

mysql>

slave2 连接slave1

启动slave

mysql> slave start;

Query OK, 0 rows affected (0.00 sec)

mysql> show slave statusG;

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

Slave_IO_State: Waiting for master to send event

Master_Host: 172.25.12.2

Master_User: redhat

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000001

Read_Master_Log_Pos: 346

Relay_Log_File: mysqld-relay-bin.000002

Relay_Log_Pos: 251

Relay_Master_Log_File: mysql-bin.000001

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

这里有问题:再究:测试:在master插入数据,在slave1,slave2上看有木有同步,同步则成功

1. mysql-bin.index:服务器一旦开启二进制日志,会产生一个与二日志文件同名,但是以.index 结尾的文件。它用于跟踪磁盘上存在哪些二进制日志文件。MySQL 用它来定位二进制日志文件。

2. mysqld-relay-bin.index:该文件的功能与 mysql-bin.index 类似,但是它是针对中继日志,而不是二进制日志。

3. master.info:保存 master 的相关信息。不要删除它,否则,slave 重启后不能连接 master。

4. relay-log.info:包含 slave 中当前二进制日志和中继日志的信息。

注意:

1.当进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,

以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。

2.mysql 数据库的版本,两个数据库版本要相同,或者 slave 比 master 版本高!

3.当在某些繁忙的OLTP(在线事务处理),当在主库上更新太多,而且从库也很多,这时从库的数据有很多没及时更新,此时需要主库"等一下"。

主库上:flush tables with read lock;

从库上:select master_pos_wait('mysql-bin.000001','199'); 这里的binlog及其位置时主库锁表时的位置点

4.当主库中有大的文本信息需要传输的时候,从服务器上可能会出现log event entry exceeded max_allowed_packet的错误。默认时1M,可以按需要在主从库上扩大max_allowed_packet。

mysql> set @@global.max_allowed_packet=16777216;

或者在配置文件中指定max_allowed_packet=16M

5. 当主库宕机时,其中一台从服务应切换成主库,其他的从库更改主库信息,应用也要相应的更改写的库。

在其中一台性能较好的从库上:
stop slave;

reset master;         ##当然开启二进制日志

删除master.info,relay-log.info文件,否则下次重启时还会按照从服务器启动。

其他从库上:

stop slave;

change master to master_host='192.168.88.122';

start salve;

应用:修改写数据库的IP。

原文地址:https://www.cnblogs.com/wxl-dede/p/5042655.html