作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
伊万·博约维奇的头像

Ivan Bojovic

Ivan拥有超过11年的MySQL经验, Oracle, PostgreSQL等数据库系统, 并且是认证的MySQL DBA.

Expertise

Previously At

European Dynamics
Share

MySQL复制是一个过程,它使数据从一个MySQL数据库服务器(主服务器)自动复制到一个或多个MySQL数据库服务器(从服务器)。. 它通常用于在多个服务器上分散读访问,以实现可伸缩性, 尽管它也可以用于其他目的,例如故障转移, 或者分析从服务器上的数据,以免使主服务器过载.

由于主从复制是单向复制(从主到从), 写操作只使用主数据库, 而读操作可能分散在多个从数据库上. 这意味着如果使用主从复制作为横向扩展解决方案, 您需要定义至少两个数据源, 一个用于写操作,另一个用于读操作.

MySQL主从复制

MySQL developers 通常只在一台机器上工作,并且倾向于将整个开发环境放在这台机器上, 其逻辑是它们不依赖于网络或Internet连接. 如果需要主从复制,因为, for example, 在其他地方部署更改之前,他们需要在开发环境中测试复制, 他们必须在同一台机器上创建它. 而单个MySQL实例的设置相当简单, 我们需要额外的努力来建立第二个, 然后是主从复制.

对于这个循序渐进的教程, 我选择了Ubuntu Linux作为主机操作系统, 所提供的命令适用于该操作系统. 如果您想在其他操作系统上设置MySQL主从复制, 您需要对其特定命令进行修改. However, 在同一台机器上设置MySQL主从复制的一般原则对于所有操作系统都是相同的.

MySQL主从复制

安装第一个MySQL实例

如果已经有一个实例 MySQL database 安装在您的机器上,您可以跳过此步骤.

在Ubuntu上安装MySQL最简单的方法是在终端提示符下运行以下命令:

安装mysql-server

在安装过程中,会提示您设置MySQL的密码 root user.

Setting Up mysqld_multi

为了有效地管理同一台机器上的两个MySQL实例,我们需要使用 mysqld_multi.

设置的第一步 mysqld_multi 创造是分开的吗 [mysqld] 现有的组 my.cnf file. Default location of my.cnf Ubuntu上的文件是 /etc/mysql/. So, open my.cnf 文件与您最喜欢的文本编辑器,并重命名现有的 [mysqld] group to [mysqld1]. 这个重命名的组将用于配置第一个MySQL实例,也将被配置为一个主实例. 在MySQL的主从复制中,每个实例必须有自己的惟一 server-id,将以下行添加到 [mysqld1] group:

server-id = 1

因为我们需要一个单独的 [mysqld] 为第二个MySQL实例复制 [mysqld1] 组与所有当前配置,并粘贴到下面的相同 my.cnf file. 现在,将复制的组重命名为 [mysqld2],并对从机的配置进行如下修改:

Server-id = 2
端口= 3307
Socket = /var/ / mysqld / mysqld_slave运行.sock
Pid-file = /var/ / mysqld / mysqld_slave运行.pid
Datadir = /var/lib/mysql_slave
Log_error = /var/log/mysql_slave/error_slave.log
Relay-log = /var/log/mysql_slave/relay-bin
Relay-log-index = /var/log/mysql_slave/relay-bin.index
master-info-file = /var/log/mysql_slave/master.info
relay-log-info-file = /var/log/mysql_slave/relay-log.info
Read_only = 1

要将第二个MySQL实例设置为从属实例,请设置 server-id 到2,因为它必须不同于主服务器的server-id.

由于两个实例将在同一台机器上运行,所以设置 port 对于第二个实例 3307因为它必须与第一个实例使用的端口不同,即 3306 by default.

为了使第二个实例能够使用相同的MySQL二进制文件,我们需要 设置不同的值 for socket, pid-file, datadir and log_error.

我们还需要启用 relay-log 为了使用第二个实例作为从属(parameters relay-log, relay-log-index and relay-log-info-file),以及设置 master-info-file.

最后,为了使从实例只读,参数 read_only is set to 1. 您应该小心使用这个选项,因为它不能完全阻止从服务器上的更改. Even when the read_only is set to 1,更新将只允许拥有 SUPER privilege. MySQL最近引入了这个新参数 super_read_only to prevent SUPER 用户进行更改. 该选项在版本5中可用.7.8.

Apart from the [mysqld1] and [mysqld2] 组,我们还需要添加一个新组 [mysqld_multi] to the my.cnf file:

[mysqld_multi]
Mysqld = /usr/bin/mysqld_safe
Mysqladmin = /usr/bin/mysqladmin
User = multi_admin
密码=多通道

一旦我们安装第二个MySQL实例, 两个都启动, 我们将给予适当的特权 multi_admin user,以便能够关闭MySQL实例.

为第二个MySQL实例创建新文件夹

在前面的步骤中,我们为第二个MySQL实例准备了配置文件. 在该配置文件中使用了两个新文件夹. 为了创建具有适当权限的文件夹,应该使用以下Linux命令:

Mkdir -p /var/lib/mysql_slave
Chmod——reference /var/lib/mysql /var/lib/mysql_slave
——引用/var/lib/mysql /var/lib/mysql_slave
 
Mkdir -p /var/log/mysql_slave
Chmod——reference /var/log/mysql /var/log/mysql_slave
——引用/var/log/mysql /var/log/mysql_slave

apapmor中的其他安全设置

在某些Linux环境中, AppArmor 为了运行第二个MySQL实例,需要进行安全设置. 至少,它们在Ubuntu上是必需的.

要正确设置AppArmor,请编辑 /etc/apparmor.d/usr.sbin.mysqld 用你喜欢的文本编辑器编辑文件,添加以下几行:

/var/lib/mysql_slave / r,
/var/lib/mysql_slave / * * rwk,
/var/log/mysql_slave / r,
/var/log/mysql_slave / * rw,
/var/ / mysqld / mysqld_slave运行.pid rw,
/var/ / mysqld / mysqld_slave运行.sock w,
/ / mysqld / mysqld_slave运行.pid rw,
/ / mysqld / mysqld_slave运行.sock w,

保存文件后,重新启动计算机,以便使这些更改生效.

安装第二个MySQL实例

安装第二个MySQL实例可以采用几种不同的方法. 本教程中介绍的方法使用与第一种方法相同的MySQL二进制文件, 使用第二次安装所需的单独数据文件.

因为我们已经在前面的步骤中准备了配置文件和必要的文件夹和安全性更改, 第二个MySQL实例的最后一个安装步骤是初始化MySQL数据目录.

执行以下命令初始化新的MySQL数据目录:

Mysql_install_db——user=mysql——datadir=/var/lib/mysql_slave . db

初始化MySQL数据目录后,可以使用 mysqld_multi service:

mysqld_multi start

Set the root 参数设置第二个MySQL实例的密码 mysqladmin 使用适当的主机和端口. 请记住,如果没有指定主机和端口, mysqladmin 默认连接到第一个MySQL实例:

mysqladmin——主机= 127.0.0.1——port=3307——u root password rootpwd

在上面的示例中,我将密码设置为“rootpwd”, 但建议使用更安全的密码.

附加配置 mysqld_multi

在“设置mysqld_multi”一节的末尾, 我写道,我们将给予适当的特权 multi_admin 用户,所以现在是时候了. 我们需要在两个实例中为该用户授予适当的权限, 让我们先连接到第一个实例:

mysql --host=127.0.0.1——port=3306 -uroot

登录后,执行以下两个命令:

mysql> GRANT SHUTDOWN ON *.*到'multi_admin'@'localhost',由'multipass'标识;
mysql> FLUSH PRIVILEGES;

退出MySQL客户端,连接到第二个实例:

mysql --host=127.0.0.1——port=3307 -uroot -p

登录后,执行与上面相同的两个命令:

mysql> GRANT SHUTDOWN ON *.*到'multi_admin'@'localhost',由'multipass'标识;
mysql> FLUSH PRIVILEGES;

退出MySQL客户端.

启动时自动启动两个MySQL实例

设置的最后一步 mysqld_multi 自动引导脚本的安装是否在 init.d.

为此,创建一个名为 mysqld_multi in /etc/init.d,并赋予它适当的特权;

cd /etc/init.d
touch mysqld_multi
chmod +x /etc/init.d/mysqld_multi

用你喜欢的文本编辑器打开这个新文件,复制下面的脚本:

#!/bin/sh

### BEGIN INIT INFO
#提供:scriptname
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1
#在启动时启动守护进程
# Description:启用daemon提供的服务.
### END INIT INFO
 
bindir=/usr/bin
 
如果test -x $ bindr /mysqld_multi
then
    mysqld_multi = " $ bindir / mysqld_multi”;
else
    echo " cannot execute $ bindr /mysqld_multi";
    exit;
fi
 
case "$1" in
    'start' )
     “$mysqld_multi”启动$2
     ;;
    'stop' )
     “$mysqld_multi”停止$2
     ;;
    'report' )
     $mysqld_multi报告$2
     ;;
    'restart' )
     “$mysqld_multi”停止$2
     “$mysqld_multi”启动$2
     ;;
    *)
     echo "Usage: $0 {start|stop|report|restart}" >&2
     ;;
esac

Add mysqld_multi 服务设置为默认值 runlevels 使用以下命令:

update-rc.mysqld_multi默认值

重新启动机器,使用以下命令检查两个MySQL实例是否正在运行:

mysqld_multi报告

设置主从复制

Now, 当我们在同一台机器上运行两个MySQL实例时, 我们将第一个实例设置为主实例, 第二个是奴隶.

在“设置mysqld_multi”一章中已经完成了部分配置。. 唯一剩下的变化是 my.cnf 文件用于在主机上设置二进制日志记录. To do this, edit my.cnf 文件中进行了以下更改和添加 [mysqld1] group:

Log_bin = /var/log/mysql/mysql-bin.log
Innodb_flush_log_at_trx_commit = 1
Sync_binlog = 1
binlog-format = ROW

重启主MySQL实例以使这些修改生效:

mysqld_multi stop 1
Mysqld_multi start

以便从服务器以正确的复制权限连接到主服务器, 应该在主服务器上创建一个新用户. 使用MySQL客户端使用适当的主机和端口连接到主实例:

Mysql -uroot -p——host=127.0.0.1 --port=3306

创建用于复制的新用户。

mysql> CREATE USER 'replication'@'%' IDENTIFIED BY 'replication';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';

退出MySQL客户端.

执行如下命令创建主数据转储:

Mysqldump -uroot -p——host=127.0.0.1 --port=3306 --all-databases --master-data=2 > replicationdump.sql

这里我们使用选项 --master-data=2 为了使注释包含 CHANGE MASTER 语句. 该注释指示备份时的复制坐标, 稍后我们将需要这些坐标来更新从实例中的主信息. 下面是这个评论的例子:

--
——开始复制或恢复的位置
--

——修改MASTER为MASTER_LOG_FILE='mysql-bin '.000001年,MASTER_LOG_POS = 349;

将上一步中创建的转储文件导入从实例:

Mysql -uroot -p——host=127.0.0.1 --port=3307 < replicationdump.sql

Finally, 为了使从实例连接到主实例, 从属服务器上的主信息需要使用适当的连接参数进行更新.

使用MySQL客户端使用适当的主机和端口连接到从实例:

Mysql -uroot -p——host=127.0.0.1 --port=3307

执行以下命令以更新主信息(从转储文件中获取复制坐标) replicationdump.sql,如上文所述):

mysql> CHANGE MASTER TO
  -> MASTER_HOST='127.0.0.1',
  -> MASTER_USER='replication',
  -> MASTER_PASSWORD='replication',
  -> MASTER_LOG_FILE='mysql-bin.000001',
  -> MASTER_LOG_POS=349;

执行如下命令启动slave:

mysql> START SLAVE;

执行以下命令验证复制是否启动并运行:

mysql> SHOW SLAVE STATUS \G

Congratulations. 在同一台机器上的MySQL主从复制现在已经成功设置.

MySQL主从复制

Wrap Up

如果您需要在生产环境中使用横向扩展解决方案,那么在开发环境中配置主从复制非常有用. This way, 您还将为写和读操作配置单独的数据源,以便在进一步部署之前在本地测试是否一切正常.

Additionally, 您可能希望在同一台机器上配置多个从属实例,以测试将读操作分发给多个从属的负载均衡器. In that case, 您可以使用相同的手册,通过重复所有相同的步骤来设置其他从属实例.

就这一主题咨询作者或专家.
Schedule a call
伊万·博约维奇的头像
Ivan Bojovic

Located in Belgrade, Serbia

Member since June 18, 2020

About the author

Ivan拥有超过11年的MySQL经验, Oracle, PostgreSQL等数据库系统, 并且是认证的MySQL DBA.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Expertise

Previously At

European Dynamics

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal Developers

Join the Toptal® community.