MariaDB GTID复制技术详解与实践
MariaDB GTID 复制技术基础
GTID 概念
全局事务标识符(Global Transaction Identifier,GTID)是 MariaDB 中用于唯一标识数据库事务的一种机制。在传统的基于日志位置的复制中,主库通过二进制日志记录数据库的修改操作,从库根据日志位置来重放这些操作。然而,这种方式在处理复杂拓扑结构和故障恢复时存在诸多不便。
GTID 的引入解决了这些问题。每个在主库上提交的事务都会被分配一个唯一的 GTID。GTID 由两部分组成:源标识符(source identifier)和事务编号(transaction number)。源标识符通常是主库的服务器 UUID,事务编号则是该服务器上自启动以来的事务序列号。例如,一个 GTID 可能看起来像 123e4567-e89b-12d3-a456-426614174000:10
,其中 123e4567-e89b-12d3-a456-426614174000
是服务器 UUID,10
是事务编号。
GTID 工作原理
- 事务提交:当一个事务在主库上提交时,主库会为该事务生成一个 GTID,并将其记录在二进制日志中。同时,该 GTID 也会被记录到主库的
gtid_executed
集合中,这个集合记录了主库上已经执行过的所有 GTID。 - 日志传输:主库将包含 GTID 的二进制日志事件发送给从库。从库接收到这些日志事件后,首先检查事件中的 GTID 是否已经在自己的
gtid_executed
集合中。如果已经存在,说明该事务已经执行过,从库会跳过这个事件;如果不存在,从库会执行这个事务,并将对应的 GTID 添加到自己的gtid_executed
集合中。 - 故障恢复:在故障恢复场景下,从库可以通过
gtid_executed
集合快速确定需要从主库重新获取哪些日志事件,而不需要依赖传统的日志位置信息。这使得故障恢复过程更加简单和可靠。
MariaDB GTID 复制配置
主库配置
- 编辑配置文件:打开 MariaDB 的配置文件(通常是
/etc/mysql/mariadb.conf.d/50-server.cnf
),添加或修改以下配置项:
[mysqld]
log-bin=mysql-bin
server-id=1
gtid-mode=ON
enforce-gtid-consistency=ON
log-bin=mysql-bin
:开启二进制日志,这是复制的基础。server-id=1
:为服务器设置一个唯一的 ID,不同服务器的 ID 不能相同。gtid-mode=ON
:启用 GTID 模式。enforce-gtid-consistency=ON
:强制 GTID 一致性,确保所有可能影响 GTID 一致性的操作都被禁止,例如某些不支持 GTID 的存储引擎操作。
- 重启 MariaDB 服务:修改配置文件后,重启 MariaDB 服务使配置生效:
sudo systemctl restart mariadb
- 创建复制用户:登录到 MariaDB 主库,创建一个用于从库连接的复制用户:
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
这里创建了一个名为 repl_user
的用户,允许来自任何主机(%
)的连接,并授予其复制从库权限。
从库配置
- 编辑配置文件:同样在从库的 MariaDB 配置文件中添加或修改以下配置项:
[mysqld]
server-id=2
gtid-mode=ON
enforce-gtid-consistency=ON
server-id
设置为与主库不同的值,这里设为 2
。其他配置与主库类似。
- 重启 MariaDB 服务:修改配置后重启服务:
sudo systemctl restart mariadb
- 配置从库连接主库:登录到 MariaDB 从库,执行以下命令配置与主库的连接:
CHANGE MASTER TO
MASTER_HOST='master_host_ip',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
MASTER_HOST
:主库的 IP 地址。MASTER_USER
和MASTER_PASSWORD
:前面在主库创建的复制用户及其密码。MASTER_AUTO_POSITION=1
:启用基于 GTID 的自动定位,从库会根据 GTID 自动确定从主库的哪个位置开始复制。
- 启动从库复制:配置完成后,启动从库的复制进程:
START SLAVE;
- 检查复制状态:使用以下命令检查从库的复制状态:
SHOW SLAVE STATUS \G;
重点关注 Slave_IO_Running
和 Slave_SQL_Running
是否都为 Yes
,以及 Seconds_Behind_Master
是否为 0 或接近 0。如果 Slave_IO_Running
为 No
,可能是网络连接或主库配置问题;如果 Slave_SQL_Running
为 No
,可能是从库执行事务时遇到错误。
MariaDB GTID 复制高级特性
GTID 与多主复制
在传统的复制拓扑中,多主复制的配置和管理比较复杂,容易出现数据冲突。而 GTID 为多主复制提供了更好的解决方案。
在多主复制环境中,每个主库都有自己唯一的 UUID。当事务在不同主库之间传播时,GTID 可以确保每个事务在整个集群中具有唯一性。例如,假设我们有两个主库 A 和 B,客户端在主库 A 上提交了一个事务,主库 A 为该事务生成 GTID A_uuid:1
。当这个事务通过复制传播到主库 B 时,主库 B 会检查自己的 gtid_executed
集合,发现该 GTID 不存在,于是执行该事务,并将 A_uuid:1
添加到自己的 gtid_executed
集合中。
为了实现多主复制,每个主库都需要配置为可以接收来自其他主库的复制连接。例如,在第二个主库的配置文件中,除了常规的 GTID 配置外,还需要设置:
log-bin=mysql-bin
server-id=3
并创建用于其他主库连接的复制用户:
CREATE USER 'repl_user_from_other_master'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user_from_other_master'@'%';
FLUSH PRIVILEGES;
然后在每个主库上,都需要使用 CHANGE MASTER TO
命令配置与其他主库的连接,例如:
CHANGE MASTER TO
MASTER_HOST='other_master_host_ip',
MASTER_USER='repl_user_from_other_master',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
GTID 与并行复制
MariaDB 的 GTID 复制支持并行复制,这可以显著提高从库的复制性能。在传统的基于日志位置的复制中,从库通常是单线程地重放主库的二进制日志,这在高并发场景下可能成为性能瓶颈。
GTID 并行复制基于 GTID 的特性,允许从库将不同的事务分配到多个线程中并行执行。从库会根据 GTID 的顺序和依赖关系,将无依赖的事务分配到不同的线程中执行。
要启用 GTID 并行复制,在从库的配置文件中添加以下配置项:
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=4
slave_parallel_type=LOGICAL_CLOCK
:设置并行复制类型为基于逻辑时钟,这是 GTID 并行复制常用的类型。slave_parallel_workers=4
:设置并行工作线程数为 4,可以根据服务器的硬件资源和负载情况进行调整。
启用并行复制后,从库在重放主库日志时,会将不同的事务分配到多个线程中并行执行,从而加快复制速度。但需要注意的是,某些事务之间可能存在依赖关系,例如一个事务更新了表 A,另一个事务依赖于表 A 的更新结果再更新表 B,这种情况下这两个事务不能并行执行,从库会根据 GTID 的逻辑时钟来确保事务执行的顺序正确性。
MariaDB GTID 复制实践案例
简单主从复制实践
- 环境准备:我们有两台服务器,一台作为主库(IP:192.168.1.100),另一台作为从库(IP:192.168.1.101),均安装了 MariaDB 10.5 版本。
- 主库配置:
- 按照前面主库配置部分的步骤,修改主库的配置文件
/etc/mysql/mariadb.conf.d/50-server.cnf
:
[mysqld]
log-bin=mysql-bin
server-id=1
gtid-mode=ON
enforce-gtid-consistency=ON
- 重启 MariaDB 服务:
sudo systemctl restart mariadb
- 创建复制用户:
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
- 从库配置:
- 修改从库的配置文件
/etc/mysql/mariadb.conf.d/50-server.cnf
:
[mysqld]
server-id=2
gtid-mode=ON
enforce-gtid-consistency=ON
- 重启 MariaDB 服务:
sudo systemctl restart mariadb
- 配置从库连接主库:
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
- 启动从库复制:
START SLAVE;
- 检查从库复制状态:
SHOW SLAVE STATUS \G;
确保 Slave_IO_Running
和 Slave_SQL_Running
都为 Yes
,Seconds_Behind_Master
为 0 或接近 0。
4. 测试复制:在主库上创建一个测试数据库和表,并插入数据:
CREATE DATABASE test;
USE test;
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));
INSERT INTO users (name) VALUES ('Alice'), ('Bob');
然后在从库上检查是否成功复制:
USE test;
SELECT * FROM users;
应该能看到与主库相同的数据。
多主复制实践
- 环境准备:现在有三台服务器,第一台主库(IP:192.168.1.100,server-id = 1),第二台主库(IP:192.168.1.101,server-id = 3),以及一台从库(IP:192.168.1.102,server-id = 2)。
- 主库 1 配置:
- 配置文件
/etc/mysql/mariadb.conf.d/50-server.cnf
:
[mysqld]
log-bin=mysql-bin
server-id=1
gtid-mode=ON
enforce-gtid-consistency=ON
- 重启服务:
sudo systemctl restart mariadb
- 创建复制用户:
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
- 主库 2 配置:
- 配置文件
/etc/mysql/mariadb.conf.d/50-server.cnf
:
[mysqld]
log-bin=mysql-bin
server-id=3
gtid-mode=ON
enforce-gtid-consistency=ON
- 重启服务:
sudo systemctl restart mariadb
- 创建复制用户:
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
- 主库间相互配置:
- 在主库 1 上配置连接主库 2:
CHANGE MASTER TO
MASTER_HOST='192.168.1.101',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
START SLAVE;
- 在主库 2 上配置连接主库 1:
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
START SLAVE;
- 从库配置:
- 配置文件
/etc/mysql/mariadb.conf.d/50-server.cnf
:
[mysqld]
server-id=2
gtid-mode=ON
enforce-gtid-consistency=ON
- 重启服务:
sudo systemctl restart mariadb
- 配置连接主库 1:
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
START SLAVE;
- 配置连接主库 2(可选,实现双活主从):
CHANGE MASTER TO
MASTER_HOST='192.168.1.101',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
START SLAVE;
- 测试多主复制:在主库 1 上创建一个新数据库和表并插入数据:
CREATE DATABASE test_multi;
USE test_multi;
CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50));
INSERT INTO products (product_name) VALUES ('Product 1');
在主库 2 上检查是否能看到相同的数据:
USE test_multi;
SELECT * FROM products;
同样,在主库 2 上进行数据操作,也应该能在主库 1 和从库上看到同步的数据。
MariaDB GTID 复制故障排查
从库复制停止
- 检查网络连接:首先确保从库与主库之间的网络连接正常。可以使用
ping
命令检查网络连通性,例如:
ping 192.168.1.100
如果网络不通,检查防火墙设置,确保 MariaDB 服务端口(默认为 3306)没有被阻塞。在 Linux 系统上,可以使用 iptables
命令查看和修改防火墙规则,例如:
sudo iptables -L
sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
- 检查主库状态:登录到主库,检查二进制日志是否正常工作。可以使用以下命令查看二进制日志状态:
SHOW MASTER STATUS;
确保 Log_name
和 Position
字段有正常的值。如果二进制日志没有正常记录,检查主库的配置文件中 log-bin
相关配置是否正确,以及磁盘空间是否充足,因为二进制日志文件会占用磁盘空间。
3. 检查从库状态:在从库上使用 SHOW SLAVE STATUS \G
命令详细查看从库状态。
- 如果
Slave_IO_Running
为No
,可能是连接主库失败。检查SHOW SLAVE STATUS \G
中的Last_IO_Error
字段,常见的错误可能是用户名密码错误、主库 IP 地址错误等。根据错误提示进行相应修改,例如,如果是用户名密码错误,可以重新使用CHANGE MASTER TO
命令修改连接配置:
CHANGE MASTER TO
MASTER_PASSWORD='new_password';
START SLAVE;
- 如果
Slave_SQL_Running
为No
,检查Last_SQL_Error
字段。可能是从库在执行事务时遇到错误,例如主库和从库之间的数据结构不一致,或者某个事务在从库上执行失败。例如,如果从库上缺少主库中某个表,需要在从库上创建相同结构的表。如果是数据类型不一致导致的错误,需要根据实际情况调整数据类型。
GTID 一致性问题
- 检查 GTID 模式配置:确保主库和从库都正确配置了 GTID 模式。在主库和从库的配置文件中,检查
gtid-mode=ON
和enforce-gtid-consistency=ON
是否正确设置,并且重启 MariaDB 服务使配置生效。 - 检查 GTID 执行集合:在主库和从库上分别使用以下命令查看
gtid_executed
集合:
SELECT @@GLOBAL.gtid_executed;
对比主库和从库的 gtid_executed
集合,确保从库的集合是主库集合的子集。如果从库的 gtid_executed
集合缺少某些 GTID,可能是复制过程中出现了问题。可以尝试在从库上使用 RESET SLAVE ALL
命令重置从库状态,然后重新配置从库连接主库:
STOP SLAVE;
RESET SLAVE ALL;
CHANGE MASTER TO
MASTER_HOST='master_host_ip',
MASTER_USER='repl_user',
MASTER_PASSWORD='password',
MASTER_AUTO_POSITION=1;
START SLAVE;
但需要注意,RESET SLAVE ALL
会清除从库的所有复制相关信息,使用前要确保了解其影响。
- 避免不支持 GTID 的操作:由于
enforce-gtid-consistency=ON
会禁止某些不支持 GTID 的操作,例如在使用不支持 GTID 的存储引擎(如 MyISAM)进行数据操作时可能会导致 GTID 一致性问题。尽量使用支持 GTID 的存储引擎,如 InnoDB。如果必须使用 MyISAM,确保在主库和从库上的操作一致,并且在操作前停止复制,操作完成后再重新启动复制。
通过以上对 MariaDB GTID 复制技术的详细介绍、配置方法、高级特性、实践案例以及故障排查,希望读者能够深入理解并熟练应用 GTID 复制技术,构建高效、可靠的 MariaDB 数据库复制架构。在实际应用中,还需要根据具体的业务需求和系统环境进行适当的调整和优化。