I. 数据库复制概述
数据库复制是指将一个数据库的数据和对象复制到另外一个或多个数据库中的过程。复制的目的是为了提高系统的可用性、可靠性和可扩展性。
A. 数据库复制的定义和作用
数据库复制是指将一个数据库中的数据和对象复制到另外一个或多个数据库中的过程。复制的目的是为了提高系统的可用性、可靠性和可扩展性。数据库复制可以分为以下几种类型:
- 主从复制:主数据库将数据和对象复制到从数据库中,从数据库只能读取数据,不能修改数据。
- 对等复制:多个数据库之间相互复制数据和对象,每个数据库都可以读取和修改数据。
- 分区复制:将一个大型数据库分成多个小型数据库,每个小型数据库都可以独立运行,但是可以相互复制数据和对象。
B. 复制的优势和应用场景
数据库复制具有以下几个优势:
- 提高系统的可用性:当主数据库出现故障时,从数据库可以立即接管工作,保证系统的正常运行。
- 提高系统的可靠性:通过将数据和对象复制到多个数据库中,可以避免单点故障,提高系统的可靠性。
- 提高系统的可扩展性:通过对等复制或分区复制,可以将一个大型数据库分成多个小型数据库,提高系统的可扩展性。
数据库复制的应用场景主要包括以下几个方面:
- 数据备份和恢复:通过将数据和对象复制到多个数据库中,可以避免因为单点故障导致数据丢失,提高数据备份和恢复的效率。
- 负载均衡:通过对等复制或分区复制,可以将负载分摊到多个数据库中,提高系统的负载均衡能力。
- 数据分析和报表生成:通过对等复制或分区复制,可以将数据分散到多个数据库中进行分析和报表生成,提高数据分析和报表生成的效率。
II. 复制类型 1 主从复制
- 主从复制是指在数据库中,将一台主机的数据复制到其他从机上的一种方式。主从复制的原理与流程如下:
- 主库将变更记录到二进制日志文件(binlog)中。
- 从库连接主库,请求从binlog中获取变更记录。
- 主库收到请求后,将binlog中的变更记录发送给从库。
- 从库接收到binlog中的变更记录后,将变更记录重放到自己的数据中。
需要注意的是,主从复制可以提高系统的可用性和可扩展性,同时也增加了系统的复杂度和维护成本。
1.2主从复制的用途与优势
主从复制是一种数据库复制技术,它将一个数据库的数据复制到另一个数据库中。主数据库负责写入数据,从数据库则负责读取数据。主从复制的主要用途是提高数据库的可伸缩性和可用性。当主数据库出现故障时,从数据库可以接管主数据库的工作,从而保证了系统的可用性。此外,主从复制还可以用于数据备份和读写分离。读写分离可以将读操作分配到从数据库中,从而减轻主数据库的压力,提高系统的性能。
1.3主从复制实战演练:配置主从复制环境,观察数据同步
1. 设置Master
在复制过程中需要完成的第一件事是安装和配置主服务器。如果你还没有安装MySQL,那么你可以使用以下命令安装MySQL:
root@repl-master:~# sudo apt-get update root@repl-master:~# sudo apt-get install mysql-server mysql-client -y root@repl-master:~# sudo mysql_secure_installation
MySQL安装过程完成后,使用以下命令编辑MySQL配置文件:
root@repl-master:~# sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
接下来,在同一文件中,找到包含 bind-address = 127.0.0.1 的行,并将该 IP 地址替换为主复制服务器的 IP 地址。因此,该行将如下所示:
bind-address = 12.34.56.111
接下来,在文件中找到以下行:
server-id = 1 log_bin = /var/log/mysql/mysql-bin.log
你会看到上面几行已经被注释掉了,只需取消这些行的注释并按 CTRL + X 退出编辑界面即可。保存更改并重新启动 MySQL 服务以使更改生效。
使用以下命令重新启动 MySQL 服务:
root@repl-master:~# sudo service mysql restart
2.为Slave创建一个新用户
下一步是为您的从服务器创建一个新用户。使用以下命令来创建它:
root@repl-master:~# mysql -uroot -p; mysql> CREATE USER ‘slave’@’12.34.56.789‘ IDENTIFIED BY ‘SLAVE_PASSWORD‘; mysql> GRANT REPLICATION SLAVE ON . TO ‘slave’@’12.34.56.222 ‘; mysql> FLUSH PRIVILEGES; mysql> FLUSH TABLES WITH READ LOCK;
您将使用以下命令来了解主服务器的当前状态:
mysql> SHOW MASTER STATUS;
该命令还将告诉从站从该位置跟随主站。
3. 将数据从主设备移动到从设备
现在您已经标记了位置,您可以开始将数据从主设备移动到从设备。您需要创建 MySQL 转储文件来移动数据。使用以下命令创建转储文件:
root@repl-master:~# mysqldump -u root -p –all-databases –master-data > data.sql
要将转储文件复制到从属设备,请使用以下命令:
scp data.sql root@12.34.56.222
使用以下命令解锁表:
mysql> UNLOCK TABLES;
4. 配置从服务器
现在,您需要做的就是配置从服务器并测试复制是否正常工作。确保已安装 MySQL。
打开从服务器中的配置文件并更新以下行:
root@repl-slave:~# sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
与主服务器的操作方式相同,您需要绑定从服务器的 IP 地址并取消注释这两行。
现在,使用以下命令重新启动 MySQL 服务器:
root@repl-slave:~# sudo service mysql restart
5. 导入数据转储
使用以下命令将转储文件导入到从服务器:
root@repl-slave:~# mysql -uroot -p < data.sql
数据导入后,需要使用以下命令停止从服务器中的MySQL:
root@repl-slave:~# mysql -uroot -p; mysql> STOP SLAVE;
您终于导入了转储文件并更新了主站 IP 地址、密码、日志文件名和位置,以使主站能够毫无问题地与从站进行通信。
6.启动从服务器
接下来,使用“Start Slave”命令开始操作从服务器。
START SLAVE;
7.测试MySQL主从复制
要测试你的MySQL主从复制是否有效,只需在主服务器中创建一个数据库,然后看看它是否在从服务器中复制。如果您可以在从站中看到数据库,则说明它工作正常。
在名为“sampledb”的主服务器中创建一个测试数据库。
CREATE DATABASE sampledb;
现在登录到您的从服务器并列出数据库,如果您在那里看到“sampledb”,则主从复制过程工作正常。
登录到您的从服务器并使用以下命令列出所有数据库:
show databases;
B. 异步复制
- mysql异步复制的特点与原理
MySQL异步复制是MySQL数据库中的一种复制方式,它的特点是主库和从库之间的数据同步是异步进行的。主库将更新操作写入二进制日志(Binary Log)中,从库通过读取主库的二进制日志实现数据同步。由于异步复制的特点,从库上的数据可能会比主库上的数据略旧一些,但是它可以提高数据库的性能和可用性。
异步复制的原理是主库将更新操作写入二进制日志,然后从库通过读取主库的二进制日志实现数据同步。从库会记录自己已经读取到的二进制日志位置,这个位置被称为“复制点”。当从库需要进行数据同步时,它会从主库的复制点开始读取二进制日志,并将日志中的更新操作应用到自己的数据库中,从而实现数据同步。
由于异步复制的特点,从库上的数据可能会比主库上的数据略旧一些。当主库出现故障时,从库可能还没有完全同步完成,此时需要进行主从切换,将从库提升为主库,让应用程序继续正常工作。但是在这个过程中,从库上可能会丢失一些更新操作,这是因为这些操作还没有被同步到从库上。因此,在使用异步复制时,需要进行定期备份和监控,并且在主从切换时需要谨慎处理以避免数据丢失。
1.2mysql异步复制的风险与适用场景
风险:
- 数据丢失:由于异步复制是在主库上记录二进制日志并将日志传输到从库,如果主库在传输日志之前出现故障,那么从库将无法获取到最新的数据,导致数据丢失。
- 数据不一致:由于异步复制有一定的延迟,可能会导致主从库之间的数据不一致。如果在主库上进行了更新操作,而从库还没有同步到这个更新操作,那么从库中的数据就会与主库不一致。
- 性能问题:由于异步复制具有更高的性能,但也可能会导致主库的性能问题。如果主库的写入负载过大,可能会导致主库的性能下降。
适用场景:
- 读写分离:异步复制常用于读写分离场景中,将读请求发送到从库中进行处理,以减轻主库的负载。
- 数据备份:异步复制也可以用于数据备份场景中,将数据备份到从库中以提高数据可靠性。
- 高可用性:异步复制也可以用于提高系统的高可用性,当主库出现故障时,可以通过从库进行故障切换。
总之,MySQL异步复制具有高性能和低延迟的优点,但也存在一些风险和适用场景需要注意。在使用时需要根据实际情况进行权衡和选择。
- 异步复制实战演练:测试异步复制的延迟和数据一致性
A. 配置异步复制环境
- 准备两台独立的 MySQL 数据库服务器
- 确保服务器之间可以互相通信 B. 配置主服务器
- 编辑主服务器的配置文件
/etc/my.cnf
- 启用二进制日志:
log-bin=master-bin
- 配置服务器唯一标识:
server-id=1
- 重启主服务器以应用配置变更 C. 配置从服务器
- 编辑从服务器的配置文件
/etc/my.cnf
- 配置服务器唯一标识:
server-id=2
- 重启从服务器以应用配置变更 D. 启动主从服务器
- 启动主服务器并开始记录二进制日志
- 启动:
mysql> FLUSH TABLES WITH READ LOCK;
以获取二进制日志文件名和位置信息,然后解锁表 2. 启动从服务器,使其连接到主服务器并开始同步
- 启动:
mysql> START SLAVE;
E. 创建数据并观察同步状态
- 在主服务器上插入新数据
- 在从服务器上观察数据同步的状态 F. 测试异步复制的延迟
- 在主服务器上连续插入数据
- 观察从服务器上数据同步的延迟 G. 测试数据一致性
- 在主服务器上修改或删除数据
- 观察从服务器上数据同步的一致性 H. 停止主从复制
- 停止从服务器的复制进程:
mysql> STOP SLAVE;
- 停止主服务器的复制进程:
mysql> RESET MASTER;
I. 验证数据同步重建
- 重新启动主从服务器
- 使用适当的命令验证从服务器的数据是否重新同步
C. 半同步复制
- MySQL半同步复制是一种 MySQL 的高可用性方案。在使用 MySQL 半同步复制时,主节点将事务先写入自己的日志中,然后将该日志传递给从节点。从节点在接收到主节点的日志后,会将日志写入自己的中继日志中,并立即返回主节点一个响应,表示该事务已经成功地被写入中继日志中。然后主节点再将该事务写入自己的二进制日志中。这个过程可以保证从节点和主节点是相对一致的,即从节点至少已经接收到了主节点的事务。这种方式相较于异步复制来说,数据的一致性和可靠性更高,但是相应的性能开销也会更大一些。
在使用半同步复制时,需要将参数“rpl_semi_sync_master_enabled”和“rpl_semi_sync_slave_enabled”设置为ON,才能开启MySQL半同步复制。此外,半同步复制是需要在主库和从库上都开启的,否则可能会导致主从不一致的情况。
半同步复制的优点在于它可以提高数据的一致性和可靠性,从而在系统出现故障时能够更快地恢复数据。例如,当主节点宕机时,从节点可以快速地接管主节点的工作,避免了系统停机的时间。此外,半同步复制还可以减少数据丢失的可能性,因为从节点上的数据与主节点上的数据是相对一致的。
当然,半同步复制也有一些缺点。首先,半同步复制会对性能造成一定的影响,因为主节点需要等待从节点的响应才能继续处理后续的事务。其次,半同步复制在从节点上可能会出现延迟的情况。如果从节点的响应时间过长,主节点可能会因等待从节点的响应而阻塞,并且可能会影响到后续的事务。同时,在进行主从切换时,半同步复制也可能会导致数据丢失的情况。
- 半同步复制实战演练:配置半同步复制,测试数据同步的可靠性
半同步复制官方手册:https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
默认情况下,MySQL的复制是异步的,master将新生成的binlog发送给各slave后,无需等待slave的ack回复(slave将接收到的binlog写进relay log后才会回复ack),直接就认为这次DDL/DML成功了。
半同步复制(semi-synchronous replication)是指master在将新生成的binlog发送给各slave时,只需等待一个(默认)slave返回的ack信息就返回成功。
MySQL 5.7对半同步复制作了大改进,新增了一个master线程。在MySQL 5.7以前,master上的binlog dump线程负责两件事:dump日志给slave的io_thread;接收来自slave的ack消息。它们是串行方式工作的。在MySQL 5.7中,新增了一个专门负责接受ack消息的线程ack collector thread。这样master上有两个线程独立工作,可以同时发送binlog到slave和接收slave的ack。
还新增了几个变量,其中最重要的是 rpl_semi_sync_master_wait_point ,它使得MySQL半同步复制有两种工作模型。解释如下。
2.半同步复制的两种类型
从MySQL 5.7.2开始,MySQL支持两种类型的半同步复制。这两种类型由变量 rpl_semi_sync_master_wait_point (MySQL 5.7.2之前没有该变量)控制,它有两种值:AFTER_SYNC和AFTER_COMMIT。在MySQL 5.7.2之后,默认值为AFTER_SYNC,在此版本之前,等价的类型为AFTER_COMMIT。
这个变量控制的是master何时提交、何时接收ack以及何时回复成功信息给客户端的时间点。
- **
AFTER_SYNC
**模式:master将新的事务写进binlog(buffer),然后发送给slave,再sync到自己的binlog file(disk)。之后才允许接收slave的ack回复,接收到ack之后才会提交事务,并返回成功信息给客户端。 - **
AFTER_COMMIT
**模式:master将新的事务写进binlog(buffer),然后发送给slave,再sync到自己的binlog file(disk),然后直接提交事务。之后才允许接收slave的ack回复,然后再返回成功信息给客户端。
画图理解就很清晰。(前提:已经设置了**sync_binlog=1
**,否则binlog刷盘时间由操作系统决定)
再来分析下这两种模式的优缺点。
AFTER_SYNC
:
- 对于所有客户端来说,它们看到的数据是一样的,因为它们看到的数据都是在接收到slave的ack后提交后的数据。
- 这种模式下,如果master突然故障,不会丢失数据,因为所有成功的事务都已经写进slave的relay log中了,slave的数据是最新的。
AFTER_COMMIT
:
- 不同客户端看到的数据可能是不一样的。对于发起事务请求的那个客户端,它只有在master提交事务且收到slave的ack后才能看到提交的数据。但对于那些非本次事务的请求客户端,它们在master提交后就能看到提交后的数据,这时候master可能还没收到slave的ack。
- 如果master收到ack回复前,slave和master都故障了,那么将丢失这个事务中的数据。
在MySQL 5.7.2之前,等价的模式是 AFTER_COMMIT ,在此版本之后,默认的模式为 AFTER_SYNC ,该模式能最大程度地保证数据安全性,且性能上并不比 AFTER_COMMIT 差。
3.半同步复制插件介绍
MySQL的半同步是通过加载google为MySQL提供的半同步插件 semisync_master.so 和 semisync_slave.so 来实现的。其中前者是master上需要安装的插件,后者是slave上需要安装的插件。
MySQL的插件位置默认存放在**$basedir/lib/plugin
**目录下。例如,yum安装的mysql-server,插件目录为/usr/lib64/mysql/plugin。
[root@xuexi ~]# find / -type f -name "semisync*" /usr/lib64/mysql/plugin/debug/semisync_master.so /usr/lib64/mysql/plugin/debug/semisync_slave.so /usr/lib64/mysql/plugin/semisync_master.so /usr/lib64/mysql/plugin/semisync_slave.so
因为要加载插件,所以应该保证需要加载插件的MySQL的全局变量 have_dynamic_loading 已经设置为YES(默认值就是YES),否则无法动态加载插件。
mysql>select @@global.have_dynamic_loading; +-------------------------------+| @@global.have_dynamic_loading | +-------------------------------+| YES | +-------------------------------+
3.1 MySQL中安装插件的方式
安装插件有两种方式:1.在mysql环境中使用**INSTALL PLUGIN
**语句临时安装;2.在配置文件中配置永久生效。
INSTALL安装插件的语法为:
1 2 3 Syntax: INSTALL PLUGIN plugin_name SONAME'shared_library_name' UNINSTALL PLUGIN plugin_name
例如,使用INSTALL语句在master上安装 semisync_master.so 插件。
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
配置文件中加载插件的方式为:
[mysqld] plugin-load='plugin_name=shared_library_name'
例如,配置文件中加载**semisync_master.so
**插件。
[mysqld] plugin-load="rpl_semi_sync_master=sermisync_master.so"
如果需要加载多个插件,则插件之间使用分号分隔。例如,在本节的slave1既是slave,又是master,需要同时安装两个半同步插件。
[mysqld] plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_sync_slave=semisync_slave.so"
安装插件后,应该使用**show plugins
**来查看插件是否真的激活。
mysql>show plugins; +----------------------+--------+-------------+--------------------+---------+| Name | Status | Type | Library | License | +----------------------+--------+-------------+--------------------+---------+ ...... | rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL | +----------------------+--------+-------------+--------------------+---------+
或者查看**information_schema.plugins
**表获取更详细的信息。
1 mysql> select* from information_schema.plugins where plugin_name like "%semi%"\\G *************************** 1. row*************************** PLUGIN_NAME: rpl_semi_sync_master PLUGIN_VERSION: 1.0 PLUGIN_STATUS: ACTIVE PLUGIN_TYPE: REPLICATION PLUGIN_TYPE_VERSION: 4.0 PLUGIN_LIBRARY: semisync_master.so PLUGIN_LIBRARY_VERSION: 1.7 PLUGIN_AUTHOR: He Zhenxing PLUGIN_DESCRIPTION: Semi-synchronous replication master PLUGIN_LICENSE: GPL LOAD_OPTION: ON 1 row in set (0.00 sec)
插件装载完成后,半同步功能还未开启,需要手动设置它们启动,或者写入配置文件永久生效。
1 # 开启master的半同步 mysql> set @@global.rpl_semi_sync_master_enabled=1; # 开启slave半同步 mysql> set @@globale.rpl_semi_sync_slave_enabled=1;
或者配合插件加载选项一起写进配置文件永久开启半同步功能。
1 [mysqld] rpl_semi_sync_master_enabled=1 [mysqld] rpl_semi_sync_slave_enabled=1
3.2 半同步插件相关的变量
安装了 semisync_master.so 和 semisync_slave.so 后,这两个插件分别提供了几个变量。
1 mysql>showglobal variableslike "%semi%"; +-------------------------------------------+------------+| Variable_name |Value | +-------------------------------------------+------------+| rpl_semi_sync_master_enabled | OFF | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_for_slave_count | 1 | | rpl_semi_sync_master_wait_no_slave |ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | | rpl_semi_sync_slave_enabled | OFF | | rpl_semi_sync_slave_trace_level | 32 | +-------------------------------------------+------------+
下面还多给了两个和半同步相关的状态变量的解释,可以通过**show status like %semi%;
**查看它们。
- master相关的变量:
- ①.
Rpl_semi_sync_master_clients
:(状态变量)master所拥有的半同步复制slave的主机数量。 - ②.
Rpl_semi_sync_master_status
:(状态变量)master当前是否以半同步复制状态工作(ON),OFF表示降级为了异步复制。 - ③.
rpl_semi_sync_master_enabled
:master上是否启用了半同步复制。 - ④.
rpl_semi_sync_master_timeout
:等待slave的ack回复的超时时间,默认为10秒。 - ⑤.
rpl_semi_sync_master_trace_level
:半同步复制时master的调试级别。 - ⑥.
rpl_semi_sync_master_wait_for_slave_count
:master在超时时间内需要收到多少个ack回复才认为此次DML成功,否则就降级为异步复制。该变量在MySQL5.7.3才提供,在此之前的版本都默认为收到1个ack则确认成功,且不可更改。MySQL 5.7.3之后该变量的默认值也是1。 - ⑦.
rpl_semi_sync_master_wait_no_slave
:值为ON(默认)或者OFF。ON表示master在超时时间内如果未收到指定数量的ack消息,则会一直等待下去直到收满ack,即一直采用半同步复制方式,不会降级;OFF表示如果在超时时间内未收到指定数量的ack,则超时时间一过立即降级为异步复制。
更官方的解释是:当设置为ON时,即使状态变量Rpl_semi_sync_master_clients中的值小于rpl_semi_sync_master_wait_for_slave_count,Rpl_semi_sync_master_status依旧为ON;当设置为OFF时,如果clients的值小于count的值,则Rpl_semi_sync_master_status立即变为OFF。通俗地讲,就是在超时时间内,如果slave宕机的数量超过了应该要收到的ack数量,master是否降级为异步复制。
该变量在MySQL 5.7.3之前似乎没有效果,因为默认设置为ON时,超时时间内收不到任何ack时仍然会降级为异步复制。 - ⑧.
rpl_semi_sync_master_wait_point
:控制master上commit、接收ack、返回消息给客户端的时间点。值为 AFTER_SYNC 和 AFTER_COMMIT ,该选项是MySQL5.7.2后引入的,默认值为 AFTER_SYNC ,在此版本之前,等价于使用了 AFTER_COMMIT 模式。关于这两种模式,见前文对两种半同步类型的分析。
- slave相关的变量:
- ①.
rpl_semi_sync_slave_enabled
:slave是否开启半同步复制。 - ②.
rpl_semi_sync_slave_trace_level
:slave的调试级别。
4.配置半同步复制
需要注意的是,"半同步"是同步/异步类型的一种情况,既可以实现半同步的传统复制,也可以实现半同步的GTID复制。其实半同步复制是基于异步复制的,它是在异步复制的基础上通过加载半同步插件的形式来实现半同步性的。
此处以全新的环境进行配置,方便各位道友"依葫芦画瓢"。
本文实现如下拓扑图所示的半同步传统复制。如果要实现半同步GTID复制,也只是在gtid复制的基础上改改配置文件而已。
具体环境:
称呼 | 主机IP | MySQL版本 | OS | 角色(master/slave) | 数据库状态 |
master | 192.168.100.21 | MySQL 5.7.22 | CentOS 7.2 | master | 全新实例 |
salve1 | 192.168.100.22 | MySQL 5.7.22 | CentOS 7.2 | semi_slave for mastersemi_master for other slaves | 全新实例 |
slave2 | 192.168.100.23 | MySQL 5.7.22 | CentOS 7.2 | semi_slave for slave1 | 全新实例 |
slave3 | 192.168.100.24 | MySQL 5.7.22 | CentOS 7.2 | semi_slave for slave1 | 全新实例 |
因为都是全新的实例环境,所以无需考虑基准数据和binlog坐标的问题。如果开始测试前,已经在master上做了一些操作,或者创建了一些新数据,那么请将master上的数据恢复到各slave上,并获取master binlog的坐标
4.1 半同步复制的配置文件
首先提供各MySQL Server的配置文件。
以下是master的配置文件。
1 [mysqld] datadir=/data socket=/data/mysql.sock log-error=/data/error.log pid-file=/data/mysqld.pid log-bin=/data/master-bin sync-binlog=1 server-id=100 plugin-load="rpl_semi_sync_master=semisync_master.so" rpl_semi_sync_master_enabled=1
以下是slave1的配置文件,注意slave1同时还充当着slave2和slave3的master的角色。
1 [mysqld] datadir=/datasocket=/data/mysql.sock log-error=/data/error.log pid-file=/data/mysqld.pid log-bin=/data/master-bin sync-binlog=1 server-id=110 relay-log=/data/slave-bin log-slave-updates plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so" rpl_semi_sync_slave_enabled=1 rpl_semi_sync_master_enabled=1
以下是slave2和slave3的配置文件,它们配置文件除了server-id外都一致。
1 [mysqld] datadir=/data socket=/data/mysql.sock log-error=/data/error.log pid-file=/data/mysqld.pid server-id=120# slave3的server-id=130relay-log=/data/slave-bin plugin-load="rpl_semi_sync_slave=semisync_slave.so" rpl_semi_sync_slave_enabled=1 read-only=on
4.2 启动复制线程
现在master上创建一个专门用于复制的用户。
1 mysql> create user repl@'192.168.100.%' identifiedby 'P@ssword1!'; mysql> grant replication slave on *.* to repl@'192.168.100.%';
因为master和所有的slave都是全新的实例,所以slave上指定的binlog坐标可以从任意位置开始。不过刚才master上创建了一个用户,也会写binlog,所以建议还是从master的第一个binlog的position=4开始。
以下是slave1上的**change master to
**参数:
1 mysql> change masterto master_host='192.168.100.21', master_port=3306, master_user='repl', master_password='P@ssword1!', master_log_file='master-bin.000001', master_log_pos=4;
以下是slave2和slave3的**change master to
**参数:
1 mysql> change masterto master_host='192.168.100.22', master_port=3306, master_user='repl', master_password='P@ssword1!', master_log_file='master-bin.000001', master_log_pos=4;
启动各slave上的两个SQL线程。
mysql> start slave;
一切就绪后,剩下的事情就是测试。在master上对数据做一番修改,然后查看是否会同步到slave1、slave2、slave3上。
5.半同步复制的状态信息
首先是semisync相关的可修改变量,这几个变量在前文已经解释过了。
例如以下是开启了半同步复制后的master上的semisync相关变量。
1 mysql> show global variables like"%semi%"; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_for_slave_count | 1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | +-------------------------------------------+------------+
关于半同步复制,还有几个状态变量很重要。
例如,以下是master上关于semi_sync的状态变量信息。
mysql>show statuslike "%semi%"; +--------------------------------------------+-------+| Variable_name |Value | +--------------------------------------------+-------+| Rpl_semi_sync_master_clients | 1 | # 注意行1 | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 5 | | Rpl_semi_sync_master_no_times | 1 | | Rpl_semi_sync_master_no_tx | 1 | | Rpl_semi_sync_master_status |ON | # 注意行2 | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 384 | | Rpl_semi_sync_master_tx_wait_time | 1537 | | Rpl_semi_sync_master_tx_waits | 4 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 4 | +--------------------------------------------+-------+
除了上面标注"注意行"的变量,其他都无需关注,而且其中有一些是废弃了的状态变量。
**Rpl_semi_sync_master_clients
**是该master所连接到的slave数量。
**Rpl_semi_sync_master_status
**是该master的半同步复制功能是否开启。在有些时候半同步复制会降级为异步复制,这时它的值为OFF。
以下是slave1上关于semi_sync的状态变量信息。
1 mysql>show statuslike "%semi%"; +--------------------------------------------+-------+| Variable_name |Value | +--------------------------------------------+-------+| Rpl_semi_sync_master_clients | 2 | # 注意行1 | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 8 | | Rpl_semi_sync_master_no_times | 2 | | Rpl_semi_sync_master_no_tx | 4 | | Rpl_semi_sync_master_status |ON | # 注意行2 | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 399 | | Rpl_semi_sync_master_tx_wait_time | 1199 | | Rpl_semi_sync_master_tx_waits | 3 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 3 | | Rpl_semi_sync_slave_status |ON | # 注意行3 +--------------------------------------------+-------+
此外,从MySQL的错误日志、**show slave status
**也能获取到一些半同步复制的状态信息。下一节测试半同步复制再说明。
6.测试半同步复制(等待、降级问题)
前面已经搭建好了下面的半同步复制结构。
1 |------> slave2 master---> slave1 --- |------> slave3
下面来测试半同步复制降级为异步复制的问题,借此来观察一些semisync的状态变化。
首先,只停掉slave2或slave3中其中一个io线程的话,slave1是不会出现降级的,因为默认的半同步复制只需等待一个ack回复即可返回成功信息。
如果同时停掉slave2和slave3的io线程,当master更新数据后,slave1在10秒(默认)之后将降级为异步复制。如下:
在slave2和slave3上执行:
mysql> stop slave io_thread;
在master上执行:
create database test1; createtable test1.t(id int); insertinto test1.tvalues(33);
在slave1上查看(在上面的步骤之后的10秒内查看):
mysql> show status like "%semi%"; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | # clients=0 | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 8 | | Rpl_semi_sync_master_no_times | 2 | | Rpl_semi_sync_master_no_tx | 4 | | Rpl_semi_sync_master_status |ON | # status=ON | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 399 | | Rpl_semi_sync_master_tx_wait_time | 1199 | | Rpl_semi_sync_master_tx_waits | 3 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 1 | | Rpl_semi_sync_master_yes_tx | 3 | | Rpl_semi_sync_slave_status |ON | +--------------------------------------------+-------+
可以看到在这一小段时间内,slave1还是半同步复制。此时用**show slave status
**查看slave1。
# slave1上执行mysql> show slave status \\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.100.21 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000004 Read_Master_Log_Pos: 1762 Relay_Log_File: slave-bin.000005 Relay_Log_Pos: 1729 Relay_Master_Log_File: master-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes ................................................ Slave_SQL_Running_State: Waiting for semi-sync ACK from slave ................................................
此时slave的SQL线程状态是**Waiting for semi-sync ACK from slave
**。
但10秒之后再查看。
mysql>show statuslike "%semi%"; +--------------------------------------------+-------+| Variable_name |Value | +--------------------------------------------+-------+| Rpl_semi_sync_master_clients | 0 | | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 8 | | Rpl_semi_sync_master_no_times | 3 | | Rpl_semi_sync_master_no_tx | 5 | | Rpl_semi_sync_master_status | OFF | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 399 | | Rpl_semi_sync_master_tx_wait_time | 1199 | | Rpl_semi_sync_master_tx_waits | 3 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 3 | | Rpl_semi_sync_slave_status |ON | +--------------------------------------------+-------+
发现slave1已经关闭半同步功能了,也就是说降级为异步复制了。
此时查看slave1的错误日志。
2018-06-11T03:43:21.765384Z 4 [Warning] Timeoutwaitingfor reply ofbinlog(file: master-bin.000001,pos: 2535), semi-syncup to file master-bin.000001,position 2292. 2018-06-11T03:43:21.765453Z 4 [Note] Semi-syncreplicationswitchedOFF.
它先记录了当前slave2/slave3中已经同步到slave1的哪个位置。然后将Semi-sync复制切换为OFF状态,即降级为异步复制。
在下次slave2或slave3启动IO线程时,slave1将自动切换回半同步复制,并发送那些未被复制的binlog。
III. 复制工具与技术A. GTID 复制
- GTID(全局事务标识符)的概念:GTID是MySQL数据库中用于标识全局事务的一种机制。它在分布式数据库环境中用于确保数据复制的一致性和可靠性。每个GTID是一个独一无二的标识符,用于标识特定的事务在数据库集群中的执行情况。GTID由以下两个主要部分组成:
- 域(Domain): 表示一个逻辑的数据库集群,通常对应于一个MySQL实例。在同一个域中,GTID是唯一的。
- 服务器编号(Server Number): 表示在特定域中的每个MySQL服务器的唯一编号。
通过将域和服务器编号组合在一起,可以创建一个全局唯一的GTID。当在数据库集群中执行事务时,每个事务都会被分配一个独一无二的GTID。
GTID复制的优势与配置:使用GTID进行数据库复制具有以下优势,并且在配置时需要考虑一些重要的参数:
优势:
- 全局唯一性: 每个事务都有一个唯一的GTID,无论是在主库上执行还是在从库上执行,这消除了传统基于binlog位置的复制中可能出现的一些问题。
- 易于配置: 相对于传统的基于文件名和位置的复制配置,GTID复制配置更加简单,避免了手动处理复制冲突等问题。
- 故障恢复: 当从库发生故障后重新加入复制时,GTID可以更可靠地定位到故障点,从而减少数据损坏的风险。
2 GTID 复制实战演练:配置 GTID 复制,演示主从切换
2.1配置MySQL源服务器
首先,通过编辑 MySQL 配置文件来配置源服务器。请密切注意确保该server-id
值是唯一的。
/etc/my.cnf.d/mysql-server.cnf
在该部分下的文件中包括以下选项[mysqld]
:
bind-address=<source_ip_address> log_bin=<path_to_source_server_log>
例如,指定沿着此路径找到日志文件:log_bin=/var/log/mysql/mysql-bin.log
。
server-id=<id>
必须server-id
是唯一的;否则,复制将无法进行。
gtid_mode=ON enforce-gtid-consistency=ON
由于您更改了配置文件,因此必须重新启动mysqld
服务:
$ sudo systemctl restart mysqld.service
2.2配置MySQL副本服务器
现在移动到副本服务器并编辑其配置文件,再次确保它server-id
是唯一的。
/etc/my.cnf.d/mysql-server.cnf
在 部分下的文件中包含以下选项[mysqld]
(如果您想了解有关选项的更多信息,请参阅 MySQL文档)。
log_bin=<path_to_source_server_log>
例如,源服务器的日志文件可能位于此处:log_bin=/var/log/mysql/mysql-bin.log
。
relay-log=path_to_replica_server_log
复制服务器的日志可能位于以下路径:relay-log=/var/log/mysql/mysql-relay-bin.log
。
server-id=<id>
必须server-id
是唯一的;否则,复制将无法进行。
gtid_mode=ON enforce-gtid-consistency=ON log-replica-updates=ON skip-replica-start=ON
您更改了副本服务器上的配置文件,因此不要忘记重新启动服务mysqld
:
$ sudo systemctl restart mysqld.service
2.3.在MySQL源服务器上创建复制用户
现在复制配置已在两台服务器上就位,下一步是在源服务器上配置必要的用户帐户。从 MySQL 命令提示符运行以下命令。
创建复制用户:
mysql> CREATE USER 'replication_user'@'replica_server_ip' IDENTIFIED WITH mysql_native_password BY 'password';
授予用户复制权限:
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'replica_server_ip';
重新加载 MySQL 数据库中的授权表:
mysql> FLUSH PRIVILEGES;
将源服务器设置为以下read_only
状态:
mysql> SET @@GLOBAL.read_only = ON;
2.4. 将副本服务器连接到源服务器
最后一步是将副本服务器与源服务器连接。这些步骤也在副本服务器上的 MySQL 提示符下执行。
将副本服务器设置为以下 read_only
状态:
mysql> SET @@GLOBAL.read_only = ON;
配置复制源:
mysql> CHANGE REPLICATION SOURCE TO -> SOURCE_HOST='source_ip_address', -> SOURCE_USER='replication_user', -> SOURCE_PASSWORD='password', -> SOURCE_AUTO_POSITION=1;
在 MySQL 副本服务器中启动副本线程:
mysql> START REPLICA;
现在取消read_only
两台服务器上的状态设置,您可以对源服务器进行更改。这些更改将发送到副本:
mysql> SET @@GLOBAL.read_only = OFF;
B. 多源复制
- 支持多个主库的复制架构:在数据库复制架构中,支持多个主库(也称为多源复制)是一种复杂的设置,可以实现数据的分布式同步和备份。这种架构可以在不同的数据中心、地理位置或业务实体之间进行数据同步,提高可用性和数据冗余。以下是实现多个主库的复制架构的关键考虑因素:
- 数据一致性: 多源复制需要确保数据在不同主库之间保持一致性。这通常需要使用分布式事务、时间戳、版本控制等机制来实现。
- 冲突解决: 当多个主库之间存在冲突时,需要一种机制来解决冲突。这可能涉及到人工干预、自动合并或基于策略的冲突解决方法。
- 拓扑管理: 确定多个主库之间的拓扑关系和数据流向。这可能包括主-从关系、主-主关系等。
- 数据分片: 如果数据量非常大,可以考虑将数据进行分片,并将不同分片同步到不同的主库。
- 监控和报警: 实时监控多源复制的状态和性能,设置适当的报警机制,以便及时处理潜在的问题。
- 故障恢复: 针对主库或复制之间的故障,需要有合适的故障恢复策略,包括自动故障切换、数据恢复等。
- 配置和管理多源复制的挑战与解决方案:配置和管理多源复制是一项具有挑战性的任务,需要考虑诸多因素。以下是一些挑战以及可能的解决方案:
- 数据冲突: 不同主库中可能存在冲突的数据更新。解决方案包括使用合适的冲突解决策略,如时间戳、版本控制,以及定义明确的数据更新规则。
- 数据一致性: 确保多个主库之间的数据保持一致性是一项复杂的任务。使用分布式事务、分布式锁、数据校验等方法来确保数据的一致性。
- 网络延迟和故障: 在不同地理位置的主库之间,网络延迟和故障可能会导致数据同步延迟或失败。采用合适的数据同步协议、重试机制和故障切换策略来应对这些问题。
- 监控和故障诊断: 多源复制的监控和故障诊断需要综合考虑多个主库的状态。使用集中式监控工具、日志分析和自动化告警系统来实时监控和检测问题。
- 性能优化: 多源复制可能会影响数据库性能。采用合理的复制策略、数据分片、定期数据清理等方法来优化性能。
- 部署和维护成本: 配置和管理多源复制需要投入相应的人力和资源。权衡成本和效益,考虑自动化部署、容器化等方式来简化部署和维护流程
C. PXC(Percona XtraDB Cluster)
- PXC 集群的特点和工作原理
PXC(Percona XtraDB Cluster)是一个基于 Galera Cluster 的 MySQL 集群解决方案。它的特点是具有高可用性、高性能和易于管理等特点。PXC 集群的工作原理是将多台 MySQL 服务器组成一个集群,集群中的每台服务器都运行着相同的数据库实例,并且相互之间通过多主同步复制技术进行数据同步。当其中一台服务器出现故障时,其他服务器会自动接管它的工作,保证了整个集群的高可用性。此外,PXC 集群还支持读写分离、负载均衡等功能,可以满足不同场景下的需求。
PXC 集群实战演练:创建 PXC 集群,测试故障转移
- Percona XtraDB Cluster 8.0概述:
- 介绍了Percona XtraDB Cluster 8.0的特点,包括基于Percona Server for MySQL 8.0、嵌入Galera writeset复制API和Galera复制库,以及与Oracle MySQL版本的一致性。
- 手动部署Percona XtraDB Cluster 8.0:
- 强调至少需要三个节点进行部署。
- 列出了节点的IP地址:db1 (192.168.20.61)、db2 (192.168.20.62)、db3 (192.168.20.63)。
- 禁用SELinux,安装Percona存储库,安装Percona XtraDB Cluster和Percona Xtrabackup。
- 配置wsrep_cluster_address,wsrep_node_address和wsrep_node_name等参数。
- 通过引导命令启动参考节点(bootstrap),启动其他节点。
- 使用ClusterControl自动部署:
- 介绍了ClusterControl的自动部署方法,需要将其部署在独立于数据库集群的主机上。
- 安装ClusterControl,并通过Web界面创建管理员用户,设置SSH无密码登录。
- 使用ClusterControl UI或CLI部署集群。
- 使用ClusterControl UI进行PXC部署:
- 在ClusterControl UI中进行Percona XtraDB Cluster的部署,指定主机和版本信息。
- 选择Percona供应商、8.0版本,输入MySQL root密码。
- 输入数据库主机的IP地址,检查SSH连接,开始部署。
- 监控部署进度,完成后在仪表板中查看集群。
- 使用ClusterControl CLI进行PXC部署:
- 使用ClusterControl命令行工具“s9s”进行部署。
- 在ClusterControl服务器上运行指令,指定节点、版本、密码等信息。
- 监视部署作业的进度。
2. 手动部署Percona XtraDB Cluster 8.0:
- 禁用SELinux:
bashCopy code $ setenforce 0 $ sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/sysconfig/selinux
- 安装Percona存储库和软件:
bashCopy code $ yum -y install <https://repo.percona.com/yum/percona-release-latest.noarch.rpm> $ percona-release setup pxc80 $ dnf -y install percona-xtradb-cluster percona-xtrabackup-80
- 编辑my.cnf文件:在每个节点的**
my.cnf
**文件中,修改以下参数(请根据实际情况进行修改):
makefileCopy code wsrep_cluster_address=gcomm://192.168.20.61,192.168.20.62,192.168.20.63 wsrep_node_address=192.168.20.61 wsrep_node_name=db1 pxc-encrypt-cluster-traffic=OFF
- 初始化和启动集群:在一个节点上执行以下命令来初始化和启动集群:
bashCopy code $ systemctl stop mysql $ systemctl start mysql@bootstrap $ systemctl status mysql@bootstrap
- 启动其他节点:在其他节点上,执行以下命令以启动集群的其他节点(逐个节点):
bashCopy code $ systemctl stop mysql $ systemctl start mysql
3. 使用ClusterControl自动部署:
- 安装ClusterControl:通过SSH连接到ClusterControl服务器,并执行以下命令:
bashCopy code $ wget <https://severalnines.com/downloads/cmon/install-cc> $ chmod 744 install-cc $ ./install-cc
- 创建管理员用户:在Web浏览器中访问ClusterControl UI,创建管理员用户,然后许可证将自动安装。
- 无密码SSH设置:在ClusterControl服务器上生成SSH密钥:
bashCopy code $ ssh-keygen -t rsa # 按照提示操作
- 将公钥复制到所有受管节点:
bashCopy code $ ssh-copy-id root@192.168.20.51 $ ssh-copy-id root@192.168.20.52 $ ssh-copy-id root@192.168.20.53
- 确保无密码SSH连接正确。
- 使用ClusterControl UI部署:在ClusterControl UI中,选择“Deploy” -> “MySQL Galera”,填写所需信息并部署。
4. 使用ClusterControl CLI进行PXC部署:
- 使用s9s工具部署:在ClusterControl服务器上运行以下命令,根据实际情况填写信息:监视作业进度。
bashCopy code $ s9s cluster --create --cluster-type=galera --nodes="192.168.20.51;192.168.20.52;192.168.20.53" --vendor=percona --provider-version=8.0 --db-admin-passwd='P4ssw0rdSecr3t' --os-user=root --os-key-file=/root/.ssh/id_rsa --cluster-name='My Percona XtraDB Cluster 8.0' --log
通过细化后的指令,您可以更详细地了解每个步骤的操作,从而更方便地完成Percona XtraDB Cluster的部署。请确保在实际操作中适当调整IP地址、密码和其他配置参数。