关于mysql:高性能Mysql主从架构的复制原理及配置详解

3次阅读

共计 14955 个字符,预计需要花费 38 分钟才能阅读完成。

复制概述

Mysql 内建的复制性能是构建大型,高性能应用程序的根底。将 Mysql 的数据分布到多个零碎下来,这种散布的机制,是通过将 Mysql 的某一台主机的数据复制到其它主机(slaves)上,并从新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并保护文件的一个索引以跟踪日志循环。这些日志能够记录发送到从服务器的更新。当一个从服务器连贯主服务器时,它告诉主服务器从服务器在日志中读取的最初一次胜利更新的地位。从服务器接管从那时起产生的任何更新,而后封闭并期待主服务器告诉新的更新。

请留神当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以防止用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的抵触。

mysql 反对的复制类型:

  • 基于语句的复制:在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句。MySQL 默认采纳基于语句的复制,效率比拟高。一旦发现没法准确复制时,会主动选着基于行的复制。
  • 基于行的复制:把扭转的内容复制过来,而不是把命令在从服务器上执行一遍. 从 mysql5.0 开始反对
  • 混合类型的复制: 默认采纳基于语句的复制,一旦发现基于语句的无奈准确的复制时,就会采纳基于行的复制。

复制解决的问题

MySQL 复制技术有以下一些特点:

  • 数据分布 (Data distribution)
  • 负载平衡(load balancing)
  • 备份(Backups)
  • 高可用性和容错行 High availability and failover

复制如何工作

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

  • master 将扭转记录到二进制日志 (binary log) 中(这些记录叫做二进制日志事件,binary log events);
  • slave 将 master 的 binary log events 拷贝到它的中继日志(relay log);
  • slave 重做中继日志中的事件,将扭转反映它本人的数据。

下图形容了复制的过程:

  • 该过程的第一局部就是 master 记录二进制日志。在每个事务更新数据实现之前,master 在二日志记录这些扭转。MySQL 将事务串行的写入二进制日志,即便事务中的语句都是穿插执行的。在事件写入二进制日志实现后,master 告诉存储引擎提交事务。
  • 下一步就是 slave 将 master 的 binary log 拷贝到它本人的中继日志。首先,slave 开始一个工作线程——I/ O 线程。I/ O 线程在 master 上关上一个一般的连贯,而后开始 binlog dump process。Binlog dump process 从 master 的二进制日志中读取事件,如果曾经跟上 master,它会睡眠并期待 master 产生新的事件。I/ O 线程将这些事件写入中继日志。
  • SQL slave thread(SQL 从线程)解决该过程的最初一步。SQL 线程从中继日志读取事件,并重放其中的事件而更新 slave 的数据,使其与 master 中的数据统一。只有该线程与 I / O 线程保持一致,中继日志通常会位于 OS 的缓存中,所以中继日志的开销很小。
  • 此外,在 master 中也有一个工作线程:和其它 MySQL 的连贯一样,slave 在 master 中关上一个连贯也会使得 master 开始一个线程。复制过程有一个很重要的限度——复制在 slave 上是串行化的,也就是说 master 上的并行更新操作不能在 slave 上并行操作。

主从复制配置

有两台 MySQL 数据库服务器 Master 和 slave,Master 为主服务器,slave 为从服务器,初始状态时,Master 和 slave 中的数据信息雷同,当 Master 中的数据发生变化时,slave 也跟着产生相应的变动,使得 master 和 slave 的数据信息同步,达到备份的目标。

要点:负责在主、从服务器传输各种批改动作的媒介是主服务器的二进制变更日志,这个日志记录着须要传输给从服务器的各种批改动作。因而,主服务器必须激活二进制日志性能。从服务器必须具备足以让它连贯主服务器并申请主服务器把二进制变更日志传输给它的权限。

环境:

  • Master 和 slave 的 MySQL 数据库版本同为 5.0.18
  • IP 地址:10.100.0.100

创立复制帐号

1、在 Master 的数据库中建设一个备份帐户:每个 slave 应用规范的 MySQL 用户名和明码连贯 master。进行复制操作的用户会授予 REPLICATION SLAVE 权限。用户名的明码都会存储在文本文件 master.info 中

命令如下:

mysql > GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* 
TO backup@’10.100.0.200’IDENTIFIED BY‘1234’;

建设一个帐户 backup,并且只能容许从 10.100.0.200 这个地址上来登陆,明码是 1234。

如果因为 mysql 版本新旧明码算法不同,能够设置:

set password for 'backup'@'10.100.0.200'=old_password('1234')

拷贝数据:(如果是你齐全新装置 mysql 主从服务器,这个一步就不须要。因为新装置的 master 和 slave 有雷同的数据)

关停 Master 服务器,将 Master 中的数据拷贝到 B 服务器中,使得 Master 和 slave 中的数据同步,并且确保在全副设置操作完结前,禁止在 Master 和 slave 服务器中进行写操作,使得两数据库中的数据肯定要雷同!

配置 master

接下来对 master 进行配置,包含关上二进制日志,指定惟一的 servr ID。例如,在配置文件退出如下值:

server-id=1
log-bin=mysql-bin
server-id:为主服务器 A 的 ID 值
log-bin:二进制变更日值

重启 master,运行 SHOW MASTER STATUS,输入如下:

配置 slave

Slave 的配置与 master 相似,你同样须要重启 slave 的 MySQL。如下:

log_bin           = mysql-bin
server_id         = 2
relay_log         = mysql-relay-bin
log_slave_updates = 1
read_only         = 1
#server_id:是必须的,而且惟一。

log_bin:slave 没有必要开启二进制日志 bin_log,然而在一些状况下,必须设置,例如,如果 slave 为其它 slave 的 master,必须设置 bin_log。在这里,咱们开启了二进制日志,而且显示的命名(默认名称为 hostname,然而,如果 hostname 扭转则会呈现问题)。

relay_log:配置中继日志,log_slave_updates 示意 slave 将复制事件写进本人的二进制日志(前面会看到它的用途)。有些人开启了 slave 的二进制日志,却没有设置 log_slave_updates,而后查看 slave 的数据是否扭转,这是一种谬误的配置。

read_only:尽量应用 read_only,它避免扭转数据(除了非凡的线程)。然而,read_only 并是很实用,特地是那些须要在 slave 上创立表的利用。

启动 slave

接下来就是让 slave 连贯 master,并开始重做 master 二进制日志中的事件。你不应该用配置文件进行该操作,而应该应用 CHANGE MASTER TO 语句,该语句能够齐全取代对配置文件的批改,而且它能够为 slave 指定不同的 master,而不须要进行服务器。如下:

mysql> CHANGE MASTER TO MASTER_HOST='server1',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='p4ssword',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=0;

MASTER_LOG_POS 的值为 0,因为它是日志的开始地位。

你能够用 SHOW SLAVE STATUS 语句查看 slave 的设置是否正确:

mysql> SHOW SLAVE STATUSG
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
...omitted...
Seconds_Behind_Master: NULL

Slave_IO_State, Slave_IO_Running, 和 Slave_SQL_Running 是 No,表明 slave 还没有开始复制过程。日志的地位为 4 而不是 0,这是因为 0 只是日志文件的开始地位,并不是日志地位。实际上,MySQL 晓得的第一个事件的地位是 4。

为了开始复制,你能够运行:

mysql> START SLAVE;

运行 SHOW SLAVE STATUS 查看输入后果:

mysql> SHOW SLAVE STATUSG
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0

在这里次要是看:

  • Slave_IO_Running=Yes
  • Slave_SQL_Running=Yes

slave 的 I / O 和 SQL 线程都曾经开始运行,而且 Seconds_Behind_Master 不再是 NULL。日志的地位减少了,意味着一些事件被获取并执行了。如果你在 master 上进行批改,你能够在 slave 上看到各种日志文件的地位的变动,同样,你也能够看到数据库中数据的变动。

你可查看 master 和 slave 上线程的状态。在 master 上,你能够看到 slave 的 I / O 线程创立的连贯:

在 master 上输出 show processlistG;

mysql> show processlist G
*************************** 1. row ***************************
Id: 1
User: root
Host: localhost:2096
db: test
Command: Query
Time: 0
State: NULL
Info: show processlist
*************************** 2. row ***************************
Id: 2
User: repl
Host: localhost:2144
db: NULL
Command: Binlog Dump
Time: 1838
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
2 rows in set (0.00 sec)

行 2 为解决 slave 的 I / O 线程的连贯。

在 slave 服务器上运行该语句:

mysql> show processlist G
*************************** 1. row ***************************
Id: 1
User: system user
Host:
db: NULL
Command: Connect
Time: 2291
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 2
User: system user
Host:
db: NULL
Command: Connect
Time: 1852
State: Has read all relay log; waiting for the slave I/O thread to update it
Info: NULL
*************************** 3. row ***************************
Id: 5
User: root
Host: localhost:2152
db: test
Command: Query
Time: 0
State: NULL
Info: show processlist
3 rows in set (0.00 sec)

行 1 为 I / O 线程状态,行 2 为 SQL 线程状态。

增加新 slave 服务器

如果 master 曾经运行很久了,想对新装置的 slave 进行数据同步,甚至它没有 master 的数据。此时,有几种办法能够使 slave 从另一个服务开始,例如,从 master 拷贝数据,从另一个 slave 克隆,从最近的备份开始一个 slave。Slave 与 master 同步时,须要三样货色:

  • (1)master 的某个时刻的数据快照;
  • (2)master 以后的日志文件、以及生成快照时的字节偏移。这两个值能够叫做日志文件坐标(log file coordinate),因为它们确定了一个二进制日志的地位,你能够用 SHOW MASTER STATUS 命令找到日志文件的坐标;
  • (3)master 的二进制日志文件。

能够通过以下几中办法来克隆一个 slave:

  • (1)冷拷贝(cold copy)
  • 进行 master,将 master 的文件拷贝到 slave;而后重启 master。毛病很显著。
  • (2)热拷贝(warm copy)
  • 如果你仅应用 MyISAM 表,你能够应用 mysqlhotcopy 拷贝,即便服务器正在运行。
  • (3)应用 mysqldump
  • <1> 锁表:如果你还没有锁表,你应该对表加锁,避免其它连贯批改数据库,否则,你失去的数据能够是不统一的。如下:
  • 应用 mysqldump 来失去一个数据快照可分为以下几步:
mysql> FLUSH TABLES WITH READ LOCK;
  • <2> 在另一个连贯用 mysqldump 创立一个你想进行复制的数据库的转储:
shell> mysqldump --all-databases --lock-all-tables >dbdump.db
  • <3> 对表开释锁。
mysql> UNLOCK TABLES;

深刻理解复制

曾经探讨了对于复制的一些根本货色,上面深刻讨论一下复制。

基于语句的复制(Statement-Based Replication)

MySQL 5.0 及之前的版本仅反对基于语句的复制(也叫做逻辑复制,logical replication),这在数据库并不常见。master 记录下扭转数据的查问,而后,slave 从中继日志中读取事件,并执行它,这些 SQL 语句与 master 执行的语句一样。

这种形式的长处就是实现简略。此外,基于语句的复制的二进制日志能够很好的进行压缩,而且日志的数据量也较小,占用带宽少——例如,一个更新 GB 的数据的查问仅须要几十个字节的二进制日志。而 mysqlbinlog 对于基于语句的日志解决非常不便。

然而,基于语句的复制并不是像它看起来那么简略,因为一些查问语句依赖于 master 的特定条件,例如,master 与 slave 可能有不同的工夫。所以,MySQL 的二进制日志的格局不仅仅是查问语句,还包含一些元数据信息,例如,以后的工夫戳。即使如此,还是有一些语句,比方,CURRENT USER 函数,不能正确的进行复制。此外,存储过程和触发器也是一个问题。

另外一个问题就是基于语句的复制必须是串行化的。这要求大量非凡的代码,配置,例如 InnoDB 的 next-key 锁等。并不是所有的存储引擎都反对基于语句的复制。

基于记录的复制(Row-Based Replication)

MySQL 减少基于记录的复制,在二进制日志中记录下理论数据的扭转,这与其它一些 DBMS 的实现形式相似。这种形式有长处,也有毛病。长处就是能够对任何语句都能正确工作,一些语句的效率更高。次要的毛病就是二进制日志可能会很大,而且不直观,所以,你不能应用 mysqlbinlog 来查看二进制日志。

对于一些语句,基于记录的复制可能更无效的工作,如:

mysql> INSERT INTO summary_table(col1, col2, sum_col3)
    -> SELECT col1, col2, sum(col3)
    -> FROM enormous_table
    -> GROUP BY col1, col2;

假如,只有三种惟一的 col1 和 col2 的组合,然而,该查问会扫描原表的许多行,却仅返回三条记录。此时,基于记录的复制效率更高。

另一方面,上面的语句,基于语句的复制更无效:

 mysql> UPDATE enormous_table SET col1 = 0;

此时应用基于记录的复制代价会十分高。因为两种形式不能对所有状况都能很好的解决,所以,MySQL 5.1 反对在基于语句的复制和基于记录的复制之前动静替换。你能够通过设置 session 变量 binlog_format 来进行管制。

复制相干的文件

除了二进制日志和中继日志文件外,还有其它一些与复制相干的文件。如下:

  • (1)mysql-bin.index

服务器一旦开启二进制日志,会产生一个与二日志文件同名,然而以.index 结尾的文件。它用于跟踪磁盘上存在哪些二进制日志文件。MySQL 用它来定位二进制日志文件。它的内容如下(我的机器上):

  • (2)mysql-relay-bin.index

该文件的性能与 mysql-bin.index 相似,然而它是针对中继日志,而不是二进制日志。内容如下:

.mysql-02-relay-bin.000017
.mysql-02-relay-bin.000018
  • (3)master.info

保留 master 的相干信息。不要删除它,否则,slave 重启后不能连贯 master。内容如下(我的机器上):I/ O 线程更新 master.info 文件,内容如下(我的机器上):

.mysql-02-relay-bin.000019
254
mysql-01-bin.000010
286
0
52813
  • (4)relay-log.info

蕴含 slave 中以后二进制日志和中继日志的信息。

发送复制事件到其它 slave

当设置 log_slave_updates 时,你能够让 slave 表演其它 slave 的 master。此时,slave 把 SQL 线程执行的事件写进行本人的二进制日志(binary log),而后,它的 slave 能够获取这些事件并执行它。如下:

复制过滤(Replication Filters)

复制过滤能够让你只复制服务器中的一部分数据,有两种复制过滤:在 master 上过滤二进制日志中的事件;在 slave 上过滤中继日志中的事件。如下:

复制的罕用拓扑构造

复制的体系结构有以下一些根本准则:

  • (1)每个 slave 只能有一个 master;
  • (2)每个 slave 只能有一个惟一的服务器 ID;
  • (3)每个 master 能够有很多 slave;
  • (4)如果你设置 log_slave_updates,slave 能够是其它 slave 的 master,从而扩散 master 的更新。

MySQL 不反对多主服务器复制(Multimaster Replication)——即一个 slave 能够有多个 master。然而,通过一些简略的组合,咱们却能够建设灵便而弱小的复制体系结构。

繁多 master 和多 slave

由一个 master 和一个 slave 组成复制零碎是最简略的状况。Slave 之间并不互相通信,只能与 master 进行通信。

在理论利用场景中,MySQL 复制 90% 以上都是一个 Master 复制到一个或者多个 Slave 的架构模式,次要用于读压力比拟大的利用的数据库端便宜扩大解决方案。因为只有 Master 和 Slave 的压力不是太大(尤其是 Slave 端压力)的话,异步复制的延时个别都很少很少。尤其是自从 Slave 端的复制形式改成两个线程解决之后,更是减小了 Slave 端的延时问题。而带来的效益是,对于数据实时性要求不是特地 Critical 的利用,只须要通过便宜的 pcserver 来扩大 Slave 的数量,将读压力扩散到多台 Slave 的机器下面,即可通过扩散单台数据库服务器的读压力来解决数据库端的读性能瓶颈,毕竟在大多数数据库利用零碎中的读压力还是要比写压力大很多。这在很大水平上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在应用相似计划解决数据库瓶颈。

如下:如果写操作较少,而读操作很时,能够采取这种构造。你能够将读操作散布到其它的 slave,从而减小 master 的压力。然而,当 slave 减少到肯定数量时,slave 对 master 的负载以及网络带宽都会成为一个重大的问题。

这种构造尽管简略,然而,它却非常灵活,足够满足大多数利用需要。一些倡议:

  • (1)不同的 slave 表演不同的作用(例如应用不同的索引,或者不同的存储引擎);
  • (2)用一个 slave 作为备用 master,只进行复制;
  • (3)用一个近程的 slave,用于劫难复原;

大家应该都比较清楚,从一个 Master 节点能够复制出多个 Slave 节点,可能有人会想,那一个 Slave 节点是否能够从多个 Master 节点下面进行复制呢?至多在目前来看,MySQL 是做不到的,当前是否会反对就不分明了。

MySQL 不反对一个 Slave 节点从多个 Master 节点来进行复制的架构,次要是为了防止抵触的问题,避免多个数据源之间的数据呈现抵触,而造成最初数据的不一致性。不过据说曾经有人开发了相干的 patch,让 MySQL 反对一个 Slave 节点从多个 Master 结点作为数据源来进行复制,这也正是 MySQL 开源的性质所带来的益处。

被动模式的 Master-Master(Master-Master in Active-Active Mode)

Master-Master 复制的两台服务器,既是 master,又是另一台服务器的 slave。这样,任何一方所做的变更,都会通过复制利用到另外一方的数据库中。

可能有些读者敌人会有一个放心,这样搭建复制环境之后,难道不会造成两台 MySQL 之间的循环复制么?实际上 MySQL 本人早就想到了这一点,所以在 MySQL 的 BinaryLog 中记录了以后 MySQL 的 server-id,而且这个参数也是咱们搭建 MySQLReplication 的时候必须明确指定,而且 Master 和 Slave 的 server-id 参数值比须要不统一能力使 MySQLReplication 搭建胜利。

一旦有了 server-id 的值之后,MySQL 就很容易判断某个变更是从哪一个 MySQLServer 最后产生的,所以就很容易避免出现循环复制的状况。而且,如果咱们不关上记录 Slave 的 BinaryLog 的选项(–log-slave-update)的时候,MySQL 基本就不会记录复制过程中的变更到 BinaryLog 中,就更不必放心可能会呈现循环复制的情景了。如图:被动的 Master-Master 复制有一些非凡的用途。例如,天文上散布的两个局部都须要本人的可写的数据正本。这种构造最大的问题就是更新抵触。假如一个表只有一行 (一列) 的数据,其值为 1,如果两个服务器别离同时执行如下语句:

# 在第一个服务器上执行:mysql> UPDATE tbl SET col=col + 1;
#在第二个服务器上执行:mysql> UPDATE tbl SET col=col * 2;

那么后果是多少呢?一台服务器是 4,另一个服务器是 3,然而,这并不会产生谬误。

实际上,MySQL 并不反对其它一些 DBMS 反对的多主服务器复制(Multimaster Replication),这是 MySQL 的复制性能很大的一个限度(多主服务器的难点在于解决更新抵触),然而,如果你切实有这种需要,你能够采纳 MySQL Cluster,以及将 Cluster 和 Replication 联合起来,能够建设弱小的高性能的数据库平台。然而,能够通过其它一些形式来模仿这种多主服务器的复制。

被动 - 被动模式的 Master-Master(Master-Master in Active-Passive Mode)这是 master-master 构造变动而来的,它防止了 M - M 的毛病,实际上,这是一种具备容错和高可用性的零碎。它的不同点在于其中一个服务只能进行只读操作。如图:

级联复制架构 Master –Slaves – Slaves

在有些利用场景中,可能读写压力差异比拟大,读压力特地的大,一个 Master 可能须要上 10 台甚至更多的 Slave 才可能撑持注读的压力。这时候,Master 就会比拟吃力了,因为仅仅连上来的 SlaveIO 线程就比拟多了,这样写的压力略微大一点的时候,Master 端因为复制就会耗费较多的资源,很容易造成复制的延时。

遇到这种状况如何解决呢?这时候咱们就能够利用 MySQL 能够在 Slave 端记录复制所产生变更的 BinaryLog 信息的性能,也就是关上—log-slave-update 选项。而后,通过二级(或者是更多级别)复制来缩小 Master 端因为复制所带来的压力。也就是说,咱们首先通过多数几台 MySQL 从 Master 来进行复制,这几台机器咱们权且称之为第一级 Slave 集群,而后其余的 Slave 再从第一级 Slave 集群来进行复制。从第一级 Slave 进行复制的 Slave,我称之为第二级 Slave 集群。如果有须要,咱们能够持续往下减少更多层次的复制。这样,咱们很容易就管制了每一台 MySQL 下面所从属 Slave 的数量。这种架构我称之为 Master-Slaves-Slaves 架构

这种多层级联复制的架构,很容易就解决了 Master 端因为从属 Slave 太多而成为瓶颈的危险。下图展现了多层级联复制的 Replication 架构。当然,如果条件容许,我更偏向于倡议大家通过拆分成多个 Replication 集群来解决

上述瓶颈问题。毕竟 Slave 并没有缩小写的量,所有 Slave 实际上依然还是利用了所有的数据变更操作,没有缩小任何写 IO。相同,Slave 越多,整个集群的写 IO 总量也就会越多,咱们没有非常明显的感觉,仅仅只是因为扩散到了多台机器下面,所以不是很容易体现进去。

此外,减少复制的级联档次,同一个变更传到最底层的 Slave 所须要通过的 MySQL 也会更多,同样可能造成延时较长的危险。

而如果咱们通过分拆集群的形式来解决的话,可能就会要好很多了,当然,分拆集群也须要更简单的技术和更简单的利用零碎架构。

带从服务器的 Master-Master 构造 (Master-Master with Slaves) 这种构造的长处就是提供了冗余。在天文上散布的复制构造,它不存在繁多节点故障问题,而且还能够将读密集型的申请放到 slave 上。 级联复制在肯定水平下面的确解决了 Master 因为所从属的 Slave 过多而成为瓶颈的问题,然而他并不能解决人工保护和出现异常须要切换后可能存在从新搭建 Replication 的问题。这样就很天然的引申出了 DualMaster 与级联复制联合的 Replication 架构,我称之为 Master-Master-Slaves 架构

和 Master-Slaves-Slaves 架构相比,区别仅仅只是将第一级 Slave 集群换成了一台独自的 Master,作为备用 Master,而后再从这个备用的 Master 进行复制到一个 Slave 集群。

这种 DualMaster 与级联复制联合的架构,最大的益处就是既能够防止主 Master 的写入操作不会受到 Slave 集群的复制所带来的影响,同时主 Master 须要切换的时候也基本上不会呈现重搭 Replication 的状况。然而,这个架构也有一个弊病,那就是备用的 Master 有可能成为瓶颈,因为如果前面的 Slave 集群比拟大的话,备用 Master 可能会因为过多的 SlaveIO 线程申请而成为瓶颈。

当然,该备用 Master 不提供任何的读服务的时候,瓶颈呈现的可能性并不是特地高,如果呈现瓶颈,也能够在备用 Master 前面再次进行级联复制,架设多层 Slave 集群。当然,级联复制的级别越多,Slave 集群可能呈现的数据延时也会更为显著,所以思考应用多层级联复制之前,也须要评估数据延时对利用零碎的影响。

复制的常见问题

谬误一:change master 导致的:

Last_IO_Error: error connecting to master 'repl1@IP:3306' - retry-time: 60  retries

谬误二:在没有解锁的状况下进行 slave 过程:

mysql> stop slave;
ERROR 1192 (HY000): Can't execute the given command because you have active locked tables or an active transaction

谬误三:在没有进行 slave 过程的状况下 change master

mysql> change master to master_host=‘IP', master_user='USER', master_password='PASSWD', master_log_file='mysql-bin.000001',master_log_pos=106;
ERROR 1198 (HY000): This operation cannot be performed with a running slave; run STOP SLAVE first

谬误四:A B 的 server-id 雷同:

Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; 
these ids must be different for replication to work (or the --replicate-same-server-id option must be used on
slave but this does not always make sense; please check the manual before using it). 
#查看 server-id
mysql> show variables like 'server_id'; 
#手动批改 server-id
mysql> set global server_id=2; #此处的数值和 my.cnf 里设置的一样就行 
mysql> slave start;

谬误五:change master 之后,查看 slave 的状态,发现 slave_IO_running 仍为 NO

须要留神的是,上述几个谬误做完操作之后要重启 mysql 过程,slave_IO_running 变为 Yes

谬误六:MySQL 主从同步异样 Client requested master to start replication from position > file size

字面了解:从库的读取 binlog 的地位大于主库以后 binglog 的值

这个别是主库重启导致的问题,主库从参数 sync_binlog 默认为 1000,即主库的数据是先缓存到 1000 条后对立 fsync 到磁盘的 binlog 文件中。当主库重启的时候,从库间接读取主库接着之前的位点从新拉 binlog,然而主库因为没有 fsync 最初的 binlog,所以会返回 1236 的谬误。

失常倡议配置 sync_binlog=1 也就是每个事务都立刻写入到 binlog 文件中。

  • 1、在从库查看 slave 状态:

偏移量为 4063315

  • 2、在主库查看 mysql-bin.001574 的偏移量地位
mysqlbinlog mysql-bin.001574 >  ./mysql-bin.001574.bak
tail -10 ./mysql-bin.001574.bak

mysql-bin.001574 文件最初几行 发现最初偏移量是 4059237,从库偏移量的 4063315 远大主库的偏移量 4059237,也就是参数 sync_binlog=1000 导致的。

  • 3、从新设置 salve
mysql> stop slave;
mysql> change master to master_log_file='mysql-bin.001574' ,master_log_pos=4059237;
mysql> start slave;

谬误 8:数据同步异常情况

  • 第一种:在 master 上删除一条记录,而 slave 上找不到。
Last_Error: Could not execute Delete_rows event on table market_edu.tl_player_task; Can't find record in'tl_player_task', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.002094, end_log_pos 286434186

解决办法:因为 master 要删除一条记录,而 slave 上找不到故报错,这种状况主上都将其删除了,那么从机能够间接跳过。可用命令:

stop slave;   
set global sql_slave_skip_counter=1;    
start slave;
  • 第二种:主键反复。在 slave 曾经有该记录,又在 master 上插入了同一条记录。
Last_SQL_Error: Could not execute Write_rows event on table hcy.t1; 
Duplicate entry '2' for key 'PRIMARY', 
Error_code: 1062; 
handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000006, end_log_pos 924

解决办法:在 slave 删除反复的主键.

  • 第三种:在 master 上更新一条记录,而 slave 上找不到,失落了数据。
Last_SQL_Error: Could not execute Update_rows event on table hcy.t1;
Can't find record in't1', 
Error_code: 1032; 
handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000010, end_log_pos 263

解决办法:把失落的数据在 slave 上填补,而后跳过报错即可。

insert into t1 values (2,'BTV');
stop slave ;set global sql_slave_skip_counter=1;start slave;

起源:https://guisu.blog.csdn.net/a…

正文完
 0