在 Debian 8 上使用 MySQL 设置主-主复制 (Jessie)
本教程适用于这些操作系统版本
- Debian 8(杰西)
- Debian 4(蚀刻)
在此页
- 1 条初步说明
- 2 安装 MySQL 5.5
- 3 一些笔记
- 4 设置复制
- 5 测试复制
- 6 个链接
本教程描述了具有 2 个节点的复制 MySQL 设置(主/主复制),其中数据可以同时读取和写入两个节点。 MySQL 负责将数据复制到另一个节点,并确保主自动增量键不会发生冲突。
从版本 5 开始,MySQL 内置了对主-主复制的支持,解决了自生成密钥可能发生的问题。在以前的MySQL版本中,master-master复制的问题是,如果节点A和节点B都在同一张表上插入了一个自增键,就会立即发生冲突。 master-master 复制相对于传统主从复制的优点是您不必修改您的应用程序以只对 master 进行写访问,并且更容易提供高可用性,因为如果 master 发生故障,您仍然有其他的主人。
1 初步说明
在本教程中,我将展示如何将数据库 exampledb 从 IP 地址为 192.168.1.101 的服务器 server1.example.com 复制到 IP 地址为 192.168.1.102 的服务器 server2.example.com,反之亦然。每个系统都是另一个主机的从机,同时也是另一个从机的主机。两个系统都运行 Debian 8;但是,该配置应该适用于几乎所有的发行版,只需很少或没有修改。
2 安装MySQL 5.5
如果 MySQL 尚未安装在服务器 1 和服务器 2 上,请立即安装:
apt-get -y install mysql-server-5.5 mysql-client-5.5
为了确保复制能够正常工作,我们必须让MySQL监听所有接口,因此我们在/etc/mysql/my.cnf中注释掉bind-address=127.0.0.1这一行:
服务器 1/服务器 2:
nano /etc/mysql/my.cnf
[...]
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address = 127.0.0.1
[...]
之后重启MySQL:
服务器 1/服务器 2:
service mysql restart
然后检查
服务器 1/服务器 2:
netstat -tap | grep mysql
MySQL 确实在监听所有接口:
netstat -tap | grep mysql
tcp 0 0 *:mysql *:* LISTEN 15437/mysqld
server1:~#
现在我们设置一个复制用户slave2_user,server2可以使用它来访问server1上的MySQL数据库。
服务器1:
登录到 MySQL shell:
mysql --defaults-file=/etc/mysql/debian.cnf
在 MySQL shell 上,运行以下命令:
服务器1:
GRANT REPLICATION SLAVE ON *.* TO '%' IDENTIFIED BY 'secretpassword';
FLUSH PRIVILEGES;
quit;
将单词 \secretpassword\ 替换为您选择的安全密码。现在我们在 server2 上再次执行最后两个步骤:
mysql --defaults-file=/etc/mysql/debian.cnf
GRANT REPLICATION SLAVE ON *.* TO '%' IDENTIFIED BY 'secretpassword';
FLUSH PRIVILEGES;
quit;
在此处也将单词 \secretpassword\ 替换为安全密码。记下密码,因为我们稍后需要它们。
3 一些注意事项
在下文中,我将假设两个 MySQL 服务器都是空的(除了 mysql 数据库外,还不包含任何数据库)。
如果您的服务器不是这种情况,那么您必须在第一台服务器上锁定并转储数据库,然后在继续之前将它们导入第二台服务器。在设置复制之前不要解锁数据库。下面的几个命令显示了如何将所有数据库复制到新服务器,以防您不以“干净”的 MySQL 设置开始。
关于如何锁定 MySQL 数据库中所有数据库表的示例。
FLUSH TABLES WITH READ LOCK;
SET GLOBAL read_only = ON;
有关如何将所有数据库转储到文件 all_databases.sql 中的示例。
mysqldump --defaults-file=/etc/mysql/debian.cnf -cCeQ --hex-blob --quote-names --routines --events --triggers --all-databases -r all_databases.sql
有关如何从文件 all_databses.sql 导入第二台服务器上的所有表的示例。
mysql --defaults-file=/etc/mysql/debian.cnf < all_databases.sql
4 设置复制
现在我们在/etc/mysql/my.cnf 中设置master-master 复制。 master-master 复制的关键配置选项是 auto_increment_increment 和 auto_increment_offset:
- auto_increment_increment 控制连续 AUTO_INCREMENT 值之间的增量。
- auto_increment_offset 确定 AUTO_INCREMENT 列值的起点。
假设我们有 N 个 MySQL 节点(本例中 N=2),然后 auto_increment_increment 在所有节点上的值为 N,并且每个节点必须有不同的 auto_increment_offset 值(1, 2, ..., N)。
现在让我们配置我们的两个 MySQL 节点:
nano /etc/mysql/my.cnf
搜索以 [mysqld] 开头的部分,并将以下选项放入其中(注释掉所有现有的 conflicting 选项):
[...]
[mysqld]
# Unique Server ID
server-id = 1
# Do not replicate the following databases
binlog-ignore-db = mysql
replicate-ignore-db = mysql
# Auto increment offset
auto-increment-increment = 2
# Do not replicate sql queries for the local server ID
replicate-same-server-id = 0
# Beginne automatisch inkrementelle Werte mit 1
auto-increment-offset = 1
# Delete binlog data after 10 days
expire_logs_days = 10
# Max binlog size
max_binlog_size = 500M
# Binlog file path
log_bin = /var/log/mysql/mysql-bin.log
[...]
然后重启MySQL:
服务器1:
service mysql restart
现在在 server2 上做同样的事情:
nano /etc/mysql/my.cnf
[...]
# Unique Server ID
server-id = 2
# Do not replicate the following databases
binlog-ignore-db = mysql
replicate-ignore-db = mysql
# Auto increment offset
auto-increment-increment = 2
# Do not replicate sql queries for the local server ID
replicate-same-server-id = 0
# Beginne automatisch inkrementelle Werte mit 1
auto-increment-offset = 2
# Delete binlog data after 10 days
expire_logs_days = 10
# Max binlog size
max_binlog_size = 500M
# Binlog file path
log_bin = /var/log/mysql/mysql-bin.log
[...]
服务器2:
service mysql restart
接下来我们锁定 server1 上的 exampledb 数据库,了解 server1 的 master 状态,创建 exampledb 的 SQL 转储(我们将导入到 server2 上的 exampledb 以便两个数据库包含相同的数据),并解锁数据库以便它可以再次使用:
现在我们开始在服务器 2 上进行复制。打开 MySQL shell:
mysql --defaults-file=/etc/mysql/debian.cnf
并执行以下 SQL 命令以激活从 server1 到 server2 的复制:
CHANGE MASTER TO MASTER_HOST='192.168.1.101', MASTER_USER='repl', MASTER_PASSWORD='secretpassword';
将 secretpassword 替换为您在第 2 章中设置的 repl MySQL 用户的密码。
现在通过在 MySQL shell 中执行命令 \show slave status\G\ 检查从属状态。
show slave status\G
输出将类似于:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.1.101
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 107
Relay_Log_File: mysqld-relay-bin.000003
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 107
Relay_Log_Space: 410
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec)
您应该检查的行是:
Master_Host: 192.168.1.101
Master_User: repl
Master_Port: 3306
Master_Log_File: mysql-bin.000001
Relay_Log_File: mysqld-relay-bin.000003
Slave_IO_Running: No
Slave_SQL_Running: No
现在在 MySQL shell 上使用此命令开始复制:
start slave;
然后再次检查从机状态:
show slave status\G
以下两行现在应该显示“是”:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
如果“Seconds_Behind_Master”不为0,则等待几秒再查看状态。该字段显示主从是否同步。
对于下一步,我们需要知道 \Master_Log_File\ 和 \Read_Master_Log_Pos\ 的值以及 \show slave status\G\ 命令。就我而言,这些是:
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 107
记下您在服务器上获得的值,我们需要它用于服务器 1 上的下一步。
之后你可以离开 MySQL shell:
quit
服务器1:
我们在第一台服务器上继续,打开服务器 1 上的 MySQL shell:
mysql --defaults-file=/etc/mysql/debian.cnf
并执行以下 MySQL 命令:
CHANGE MASTER TO MASTER_HOST='192.168.1.102', MASTER_USER='repl', MASTER_PASSWORD='secretpassword', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=107;
你必须在上面的命令中替换一些东西:
- IP 地址必须是您的第二个 MySQL 服务器的 IP。
- 密码“secretpassword”必须是您在第 2 章中为用户 repl 选择的密码。
- MASTER_LOG_FILE 和 MASTER_LOG_POS 必须是我们在上一步中记下的值。
现在检查:
show slave status\G
如果没有错误,在 MySQL shell 上。
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.1.102
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 107
Relay_Log_File: mysqld-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 107
Relay_Log_Space: 107
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
1 row in set (0.00 sec)
并启动奴隶。
start slave;
再次查看slave状态:
show slave status\G
以下两行现在应该显示“是”:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
之后你可以离开 MySQL shell:
quit
如果没有出错,MySQL 主-主复制现在应该可以工作了。如果不是,请检查 /var/log/syslog 以了解 server1 和 server2 上的 MySQL 错误。
5 测试复制
现在是时候测试我们的复制设置了。我将在服务器 1 上创建一个数据库 exampledb1,然后在服务器 2 上检查数据库是否已复制到第二台服务器:
在 server1 上登录 MySQL 控制台并创建数据库:
mysql --defaults-file=/etc/mysql/debian.cnf
CREATE DATABASE exampledb1;
服务器2
现在登录到 server2 上的 MySQL 控制台并检查 exampledb1 现在是否存在:
mysql --defaults-file=/etc/mysql/debian.cnf
show databases;
正如我们所见,新数据库也出现在 server2 上。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| exampledb1 |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
接下来我将测试复制是否在另一个方向上也有效。我们仍然登录到 server2 并在那里创建一个数据库 exampledb2:
CREATE DATABASE exampledb2;
现在回到 server1 并在 MySQL 控制台中运行“show databases”:
服务器1
show databases;
结果显示我们的新数据库 exampledb2,因此复制在两个方向上进行。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| exampledb1 |
| exampledb2 |
| mysql |
| performance_schema |
+--------------------+
5 rows in set (0.01 sec)
6个链接
- MySQL:http://www.mysql.com
- Debian:http://www.debian.org