MySQL 主从架构配置详解

无论是哪一种数据库,数据的安全都是至关重要的,因此熟练掌握数据库的安全备份功能,是作为开发人员,特别是后端开发人员的一项必备技能。MySQL 数据库内建的复制功能,可以帮助我们对数据进行异地备份,读写分离,在较大程度上避免数据丢失、数据库服务器压力过大甚至宕机带来的损失。

使用MySQL 主从架构一年多了,想起当年学习这些东西的时候,苦于完整的中文资料比较少,当时英文又不太好,遇到不少问题。刚好最近也有一段时间没更新博客了,心血来潮,决定翻译一下 MySQL 官网的英文文档,官网文档讲解的非常详细,可以帮助更多新手理解并快速入门。

第一次翻译这么大篇幅的英文技术文档,尽量采取逐句翻译,这样可以尽可能保持文档原意。有很多需要修改的地方,恳请各位指正。

废话说多了,下面开始~~~

概述

MySQL的复制功能,使得数据可以从一台MySQL 数据库服务器(我们称之为主库,即 master),复制到另外一台或者多台MySQL 数据库服务器(我们称之为从库,即 slave)。在默认情况下,复制的过程是异步的,因此,从数据库服务器不需要一直连接到主数据库服务器接收更新。 这也意味着,更新可以在长距离连接,甚至在诸如拨号服务临时或者间歇性的情况下继续。MySQL的复制功能,可以复制所有数据库,或者需要复制的几个数据库,甚至数据库中需要复制的数据库表,这都依赖于你是如何配置的。

配置

配置主库

需要复制的主库必须开启二进制日志功能,并且创建一个唯一的服务器编号(server-id),之后,必须重启数据库。

由于二进制日志文件是主从复制的基础,所以,主库 必须 开启二进制日志功能。如果二进制日志功能没用使用 log-bin选项开启,主从复制就无法进行。

可以将所有的从库作为一个组,组里的每一个从库都需要创建一个唯一的服务器编号(server-id),以便用这个编号在组里识别指定的从库,数据库服务器编号(server-id)必须是 1 至 232 − 1 之间的整数。具体使用哪些整数,完全由你自己决定,没有其他特殊规定。

要给数据库配置服务器编号(server-id)选项,需要停止MySQL 数据库,然后编辑 my.cnf 或者 my.ini 文件。在配置文件的 [mysqld] 这一节下,添加 log-bin 和 server-id 两个选项。如果它们已经存在,但是被注释掉了,就解注释,然后根据自己的需要进行修改。例如使用前缀为mysql-bin日志文件名,启用二进制日志功能,配置服务器编号为1,可以参考下面的示例:

[mysqld]
log-bin=mysql-bin
server-id=1

保存好上面的修改之后,重启数据库。

注意:

  • 如果没有配置 server-id 选项(或者将其设置为默认值0),主库将拒绝来自任何从库的连接请求。
  • 为了能在 InnoDB 存储引擎中使用事务时,达到最大可能的耐用性和一致性,需要在 my.cnf 文件中配置innodb_flush_log_at_trx_commit=1 和 sync_binlog=1 两个选项。
  • 不要在主库上配置 skip-networking 选项。如果主库的网络都被禁用了,从库就不能连接到主库,最终导致复制失败。

配置从库

前面在配置主库时,已经说过,必须给每个从库创建一个服务器编号,创建好之后,必须 重启数据库。

如果从库的服务器编号没有设置,或者设置的编号和主库冲突,就需要先停掉从库,然后编辑从库的配置文件的[mysqld] 这一节,指定一个唯一的服务器编号,像下面这样:

[mysqld]
server-id=2

保存好修改之后,重启从库。

如果配置了多个从库,那么每一个从库都必须有一个唯一的 server-id 选项值(即每个从库的 server-id 值必须与主库以及除它本身以外的其他从库的 server-id 值不同)。

注意:
如果没有配置从库的 server-id 选项(或者配置它的值为默认值0),那么从库将拒绝连接到主库。

不需要为了主从复制而给从库开启二进制日志功能。如果给从库开启了二进制日志功能,由此产生的二进制日志文件可以作为备份数据,或者在数据库崩溃的时候,使用二进制日志文件恢复数据,也可以使用此开启了二进制日志功能的从库作为更复杂的主从架构的一部分。比如,可以将此从库作为其他从库的主库。

为从库创建用户

每个从库都使用数据库用户名和密码连接并登录到主库,所以在主库中必须有一个能让从库连接到此主库的 MySQL 账户。任何被赋予 REPLICATION SLAVE 权限的 MySQ L账户,都可以用作此连接操作。可以为每一个从库分配一个账户,也可以让所有的从库使用同一个账户,用来连接到主库。

虽然不需要为从库分配一个单独的账户去执行复制,但你应该知道的是,用来复制操作的用户名和密码都是明文存储在主库文件或表中的(相关链接:Section 17.2.2.2, “Slave Status Logs”)。因此,你可能想要创建一个隔离的、只能进行复制操作的账户,将对其他账户的损害减到最小。

使用 CREATE USER 语句创建新的 MySQL 账户。使用 GRANT 语句给这个账户赋予复制操作所必要的权限。若创建账户仅是为了达到复制的目的的话,那么这个账户只需要 REPLICATION SLAVE 。举个例子,创建一个新的账户 repl ,使其可以从 mydomain.com 域名下的任何主机连接到主库并执行复制,在主库上执行下面的语句:

CREATE USER 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.mydomain.com';

更多关于用户账户的操作语句,请查看 Section 13.7.1, “Account Management Statements”

获取主库的二进制日志坐标

为了在接下来配置完从库,使其能从正确的位置开始执行复制操作,你需要知道主库当前的二进制日志坐标。

如果在主库上已经存储了一些数据,而且又需要在开始之前同步到从库上,那么就必须在主库上停止执行语句,接着,获取主库当前的日志坐标,并转存其数据。如果不使主库停止执行语句,将会导致转存的数据和数据库的状态信息不相符,最终导致从库数据不一致或者引起从库发生错误。

依照下面这几步来获取主库的二进制日志坐标:

  1. 使用命令行连接到主库以开始一个会话,清空所有表的缓存,并且通过执行 FLUSH TABLES WITH READ LOCK 阻止对数据库的写操作,即锁定对所有表的只读操作:
    FLUSH TABLES WITH READ LOCK

    对于 InnoDB 存储引擎来说, FLUSH TABLES WITH READ LOCK 语句也会阻止 COMMIT 操作。

    提醒:
    不要退出刚才执行了 FLUSH TABLES 语句的会话。如果退出了这个会话,上面的锁表操作将被释放。

  2. 再打开一个新的会话,连接到主库,使用 SHOW MASTER STATUS 语句来确认当前二进制日志文件的名称和位置:
    SHOW MASTER STATUS;

    结果:

    File Position Binlog_Do_DB Binlog_Ignore_DB
    mysql-bin.000003 73 test manual,mysql

    File 列显示了当前二进制日志文件的名字, Position 列显示了文件的位置。在上面这个例子中,二进制日志文件的名字是 mysql-bin.000003 ,位置是 73 。这些数据代表了从库将要(开始)处理来自主库的更新的坐标。记录下这些数据,稍后在配置从库时,将会使用到它们。

    如果主库在事先没有开启二进制日志功能时已经在运行状态了,那么,通过执行 SHOW MASTER STATUS 语句,或者通过执行 mysqldump –master-data 命令,得到的结果中,二进制日志文件名和位置都将是空。若是那样的话,在从库上配置二进制日志名和位置时,就分别用空字符串('')和 数值 4 来代替。

到目前为止,我们已经获得了足够的信息,我们需要使用这些信息,配置从库,使从库开始从正确的位置读取来自主库的二进制日志,开始进行复制。

如果你有一些数据,需要在从库开始复制之前同步到从库,那么,保持之前开启的会话不要关闭,这样才能保持之前开启的数据库锁不被释放。接着,查看 Section 17.1.1.5, “Creating a Data Snapshot Using mysqldump” 或者 Section 17.1.1.6, “Creating a Data Snapshot Using Raw Data Files” 。它们将会告诉你如何防止任何进一步的更改,以便于将已经存在于主库的数据同步到从库。

如果你正在建立一个全新的主从复制组,你可以退出第一个会话,以便释放对数据库的读锁定。

使用新的主、从库配置复制

使用新的主、从库配置数据库复制是最简单、最直接的方式。

如果你正在设置新的服务器,但是有一些从其他的务器转存的数据库,并且你想加载到你的复制配置新中,同样可以使用本节介绍的方法。通过将数据加载到新的主库中,数据将会被自动复制到从库中。

依照下面这几步,来在新的主、从库之间配置复制功能:

  1. 通过一些必要的配置属性文件,配置主库。参考:配置主库
  2. 启动主库。
  3. 设置一个用户。参考:为从库创建用户。
  4. 获取主库的状态信息。参考:获取主库的二进制日志坐标。
  5. 在主库上释放读锁:
    UNLOCK TABLES;
  6. 在从库上编辑 MySQL 配置文件。 参考:配置从库。
  7. 启动从库。
  8. 执行 CHANGE MASTER TO 语句来设置主库的信息。参考:为从库配置主库的信息。

在每一台从库上,都完成上面这几步操作。

因为使用的是新的数据库,没有数据或者配置信息需要替换,因此你不需要复制或者导入任何其他信息。

如果你需要使用来自于其他数据库服务器上数据配置新的复制环境,你可能需要在新的主库上导入这些转存的数据。由此对主库产生的更新将会被自动同步到从库:

mysql -h master < fulldb.dump

使用已有的数据配置复制环境

当使用已有的数据配置复制环境时,你可能需要做出一个决定,如何在启动复制服务之前,让从库以最优方式获取到主库的数据。
下面这几步基本操作将会引导你,使用已有的数据配置复制环境:

  1. 在 MySQL 主库运行的情况下,创建一个用户,以便从库在复制的时候可以连接到主库。参考:为从库创建用户。
  2. 如果你还没有在主库上配置 server-id 选项,或者还没有开启二进制日志功能,你需要停止主库,然后配置它们。参考:配置主库。
    在配置主库的过程中,如果需要停止(重启)主库服务,你可以利用主库服务停止的这段时间,创建一个主库的快照。但别忘了,你需要在停止主库服务、更新配置信息,创建快照之前,获得主库的状态信息(参考:获取主库的二进制日志坐标)。关于如何使用原始数据创建数据库快照,你可以参考这里:Section 17.1.1.6, “Creating a Data Snapshot Using Raw Data Files”
  3. 如果主库信息已经正确配置好了,那么就可以获取它的状态信息(参考:获取主库的二进制日志坐标),接着,使用 MySQL 自带的 mysqldump 工具创建一个数据库快照(参考:Section 17.1.1.5, “Creating a Data Snapshot Using mysqldump”),也可以参考 Section 17.1.1.6, “Creating a Data Snapshot Using Raw Data Files” 直接创建主库的原始数据文件的快照。
  4. 更新从库的配置信息。参考:配置从库。
  5. 这一步的操作,取决于你在主库上是如何创建的数据的快照的。
    若你是使用的 mysqldump 创建的快照:

    • 使用 --skip-slave-start 选项启动从库,以便不让主从复制开始。
    • 像下面这样,导入转存的数据文件:
      mysql < fulldb.dump

    若你是使用第二种方案,即直接创建原始数据文件的快照的方式:

    • 将数据文件解压到从库的数据(data)目录下:
      tar xvf dbdump.tar

      你可能需要设置这些文件的权限和所有者,以便在从库可以获取到这些数据文件,并且可以对其进行更新。

    • 使用 --skip-slave-start 选项启动从库,以便不让主从复制开始。
  6. 将主库的二进制日志坐标信息配置到从库。这一步用来指定从库需要从主库的哪一个二进制日志文件,以及从这个文件的什么位置开始复制。当然,也需要在从库上配置连接主库时使用的凭证和主库的 IP 或者 域名。更多关于CHANGE MASTER TO 语句的所需的必须参数等信息,请参考:为从库配置主库的信息。
  7. 启动从库:
    START SLAVE;

执行完上面这几步,从库就会连接到主库,主库的任何更新操作,都将被发送到从库,从库会在已有的快照数据的基础上,同步执行这些更新。

如果你忘记了设置主库的 server-id 选项信息,从库将无法连接到主库。

如果你忘记了设置从库的 server-id 选项信息,在从库的错误日志中,将出现以下错误信息:

Warning: You should set server-id to a non-0 value if master_host
is set; we will force server id to 2, but this MySQL server will
not act as a slave.

同样,如果从库由于其他任何原因导致不能执行复制,你可以在错误日志文件中得到相关的错误信息。

从库通过使用存储在主库信息仓库中的信息,保持跟踪它已经执行了多少主库产生的二进制日志。通过 --master-info-repository 选项,可以将仓库信息设置在文件的表单里,或者在一个表中。当配置信息为 --master-info-repository=FILE 时,你可以在从库的数据(data)目录下发现两个文件,名字分别是 master.info 和 relay-log.info 。配置信息为 --master-info-repository=TABLE 时,信息将会被保存在 mysql 数据库的 master_slave_info表中。无论如何,不要删除或者编辑上面提到的文件和表里的数据,除非你清楚的知道你在干什么,并且充分理解这么做代表的含义。即便如此,也应该优先使用 CHANGE MASTER TO 语句去修改复制参数。从库可以使用语句中指定的值去自动更新状态信息文件。更多相关信息请参考:Section 17.2.2, “Replication Relay and Status Logs”

注意:
主库信息仓库的内容会覆盖一些在命令行或者 my.cnf 文件中设置的选项。详细信息请参考:Section 17.1.4, “Replication and Binary Logging Options and Variables”

一份主库的快照,可以被多个从库来使用。如果需要额外再配置一些从库,可以使用相同的主库快照,像之前介绍如何配置已有从库时描述的那样,配置这些额外增加的从库。

为从库配置主库的信息

你必须告诉告诉从库一些必要信息,以便从库能够连接到主库进行复制。为了做到这一点,在从库上执行下面的语句,根据你的系统上实际的值,替换语句中相应的选项值:

CHANGE MASTER TO MASTER_HOST='master_host_name', MASTER_USER='replication_user_name', MASTER_PASSWORD='replication_password', MASTER_LOG_FILE='recorded_log_file_name', MASTER_LOG_POS=recorded_log_position;

注意:
复制不能使用 Unix 套接字文件(socket file)。你必须确保能够使用 TCP/IP 协议连接到主库。

CHANGE MASTER TO 语句也有一些其他参数可供配置。例如,可以通过使用此语句的其他选项,决定是否使用 SSL 协议,以便达到安全的复制。

关于此语句的完整的选项,以及选项值允许的最大长度等信息,请参考:Section 13.4.2.1, “CHANGE MASTER TO Syntax”