写点什么

GreatSQL 异步复制及搭建

作者:GreatSQL
  • 2024-09-11
    福建
  • 本文字数:3804 字

    阅读完需:约 12 分钟

GreatSQL 异步复制及搭建

一、简介

复制就是将一个数据库数据复制到一个或多个数据库上,复制的过程是异步的,其工作原理是通过 binlog(二进制日志)记录事务变更然后传送到从库并重放事务,保持数据一致

二、复制过程


1-1 复制过程图

2.1 binlog 日志

GreatSQL 复制是基于 binlog 日志来实现复制的

2.1.1 二进制日志输出格式比较

2.2 复制过程

  1. 主库把数据更新事件写入二进制日志。

  2. 从库的 IO 线程向主库请求二进制日志事件。

  3. 主库的 binlog dump 线程向从库 IO 线程发送二进制日志事件。

  4. 从库的 IO 线程将二进制日志事件写入中继日志。

  5. 从库的 SQL 线程应用中继日志中的事件。

2.3 二阶段提交

GreatSQL 包含两种记录数据变更的日志,redolog、binlog 为了保证两个日志的对数据变更事件达到一致性,GreatSQL 内部使用 XA 来实现,其核心是两阶段提交。

2.3.1 事务提交流程

主从复制中,从库是通过 binlog 日志重放来实现复制。如何保证主从的数据一致性,就需要考虑如下两方面


  1. binlog 记录的事务一定不比 redolog 少。

  2. binlog 与 redolog 记录的事务的顺序性是一致的。


在两阶段协议中一般分为事务管理器(协调者)和若干事务执行器(参与者)两种角色。GreatSQL 内部实现的两阶段提交中,二进制日志充当了协调组角色,由它来通知 InnoDB 执行准备、提交和回滚。从实现角度分析,事务提交有准备阶段和提交阶段组成。两阶段提交流程如下图:



1-2 事务提交流程


1、事务发起 commit 请求。


2、调用 binlog-hton 和 innobase-hton 的 prepare 方法完成第一阶段。binlog-hton 的方法什么也没有做,innodb 的 prepare 持有 prepare_commit_mutex 锁,将重做日志刷盘,并将事务状态设置为 prepared。


3、如果事务涉及的所有存储引擎的 prepare 都执行成功,则调用 TC_LOG_BIN:log_xid 将事务写入到二进制日志。


4、最后,调用存储引擎的 commit 完成事务的提交,向重做日志写入 commit 标记,释放 prepare_commit_mutex,并将事务设置为 trx_not_started 状态。

2.3.2 InnoDB 恢复

数据库在奔溃恢复时,不同状态的事务,会进行不同的处理。


  • trx_commit_in_memory 的事务,清除回滚段后,将事务设置为 trx_commit_not_started。

  • trx_commit_active 的事务,直接回滚。

  • trx_not_started 的事务,表示事务已提交过,跳过。

  • trx_commit_prepared 的事务,要根据二进制日志来决定事务是否提交,暂时跳过。


在数据库发生奔溃时,数据库根据重做日志进行数据恢复,逐个检查重做日志的每个事务状态。根据 1-2 的流程,如果已经进行到 trx_not_started 阶段,也就是存储引擎 commit 阶段,那么说明重做日志和二进制日志是一致的,正常根据重做日志的内容进行恢复即可。如果事务状态为 trx_active,没有写入到二进制日志,就直接回滚。如果事务状态为 trx_commit_prepared,要分两种情况:先检查二进制日志是否写入成功,如果没有写入成功,直接回滚,如果写入成功了,那就进行最后一步,调用存储引擎 commit,更改事务状态为 trx_not_started,也就是真正提交的状态,可以用作数据恢复。


由此可以,GreatSQL 是以二进制日志的写入与否作为事务提交成功与否的标志。通过这种方式让 InnoDB 重做日志和 GreatSQL 服务器的二进制日志中的事务状态保持一致。两阶段提交很好的保持了数据的一致性和顺序性。


GreatSQL 通过 innodb_support_xa 系统变量来控制 innodb 是否支持 XA 事务的两阶段提交,默认是支持。在 GreatSQL8 中已移除该变量,表示数据库内部一直启用 innodb 对 XA 事务两阶段提交的支持。

2.3.3 日志刷盘频率

两阶段提交只是从流程上保证了日志的一致性,如果日志在写盘期间,数据库发生了崩溃或者服务器宕机,存在日志数据丢失的风险。为了规避此类风险,我们需要配置正确的日志刷盘频率。


重做日志的刷盘频率由 innodb_flush_log_at_commit_trx 参数控制。二进制日志的刷盘频率由 sync_binlog 参数控制。


  • 重做日志刷盘方式

  • innodb_flush_log_at_trx_commit 参数为 1 时,表示只要事务提交,立即将重做日志刷盘。

  • innodb_flush_log_at_trx_commit 参数为 2 时,表示每秒将重做日志缓冲区的内容写入到操作系统页面缓冲,至于什么时候刷盘,由操作系统控制。

  • innodb_flush_log_at_trx_commit 参数为 0 时,表示每秒将重做日志刷盘。

  • 二进制日志刷盘方式

  • sync_binlog 参数为 1 时,表示只要事务提交,立即将二进制日志刷盘。

  • sync_binlog 参数为 N(N>1)时,表示 N 个二进制日志组提交后,将二进制日志刷盘。

  • sync_binlog 参数为 0 时,表示二进制日志的刷盘由操作系统控制。

三、异步复制参数

3.1 源库和复制库常用参数说明

四、异步复制部署

4.1 环境准备

使用两台服务器来部署一主一从的异步复制。


Master:192.168.135.183


Slave:192.168.135.142

4.2 部署数据库

安装 GreatSQL 数据库


见 GreatSQL 官方文档 https://greatsql.cn/docs/8.0.32-25/4-install-guide/3-install-with-tarball.html

4.3 配置复制

4.3.1 空库

初始安装的数据库没有任何应用数据。可以直接配置就能使用。


  • Master 上的操作:

  • Slave 上的操作:

4.3.2 脱机

如果源数据库上存在应用数据,允许在一个接收的脱机时间窗口进行复制,那么我们可以直接把源库的数据文件复制到从库,再启动从库进行主从配置。


  • Master 上的操作

  • 创建用于复制的账户,并授予相应的权限。

  • 停止源数据库服务。

  • 复制源数据库上的数据文件到从库。

  • 启动源数据库服务。

  • Slave 上的操作

  • 删除从库数据目录中的 auto.cnf,从库在启动时会自动生成唯一的 server_uuid。检查数据库配置文件确保 server_id 是唯一的。

  • 启动从数据库服务。

  • 配置主从同步关系,并启动主从同步线程。

4.3.3 联机

大多数情况下,复制被要求在不影响线上业务的情况下联机创建,而且还要求对线上源库影响越小越好。在联机情况下,我们通常采用 mysqldump 和 xtrabackup 工具复制源库到从库,配置主从同步。


mysqldump 联机复制过程


  • Master 上的操作


​ 1.创建用于复制的账户


greatsql> create user repl@'%' identified with mysql_native_password by '!QAZ2wsx';greatsql> grant replication client,replication slave on *.* to repl@'%';greatsql> flush privileges;
复制代码


  • Slave 上的操作


  1. 创建源库信息


greatsql> change master to master_host='192.168.135.183',master_port=3305,master_user='repl',master_password='!QAZ2wsx';
复制代码


  1. 使用 mysqldump 导入数据到从库,建立复制


greatsql> mysqldump --single-transaction --all-databases --master-data=1 --host=192.168.135.183 --port=3306 --user=root --password=!QAZ2wsx --default-character-set=utf8mb4 --apply-slave-statements|mysql -uroot -p!QAZ2wsx -h192.168.135.142 -P3305
复制代码


重要参数说明:


  • --single-transaction 参数对 innodb 表执行非锁定导出。此选项将事务隔离模式设置为 repeatable read,并在转储数据之前向服务器发送 start transaction sql 语句。它仅适用于 innodb 等事务表,因为它会在发出 start transaction 时转储数据库一致状态,而不会阻塞任何应用程序。

  • --master-data 参数为 1 时会导致转储输出包含类型 change master to master_log_file='binlog.000004',master_log_pos=1230;的 sql 语句,该语句指示主库的二进制日志坐标(文件和偏移量)。如果选项值为 2,则 chang master to 语句将被注释,仅提供信息,不会执行。如果未指定选项值,则默认值为 1。

  • --apply-slave-statements 参数会在 change master to 之前添加 stop slave 语句,被宰输出的结尾处添加 start slave 语句,用于开启复制。

  • --deafult-character-set 参数指定默认字符集,GreatSQL 的默认字符集为 utf8mb4。


xtrabackup 联机复制过程


  • Master 上的操作

  • 在源库上创建全量备份

  • 准备数据信息备份


--prepare参数准备备份数据进行恢复。数据文件在准备之前是不一致的,因为它们是在备份程序运行的不同时间复制的,并且在这个时间段,有些数据已经发生变更。其原理是使用 redolog 进行后滚,使用 undolog 进行前滚。


  • Slave 上的操作

  • 关闭从库,在从库上删除数据库初始化生成的数据库文件。

  • 从源库上拉取备份恢复后的数据文件。

  • 启动从数据库服务,并配置主从同步。

五、异步复制常见问题说明

5.1 show slave 重点指标说明

我们在从库执行 show slave status 来观察主从同步的状态。


  • master_log_file:I/O 线程正在读取的 master binlog。

  • read_master_log_pos:I/O 线程已经读取到 master binlog 的位置。

  • relay_log_file:SQL 线程正在读取和执行的 relay log。

  • relay_log_pos:SQL 线程已经读取和执行 relay log 的位置。

  • relay_master_log_file:SQL 线程最近执行的操作对应的是哪个 master binlog。

  • relay_master_log_pos:SQL 线程最新执行的操作对应的是 master binlog 的位置。

  • retrieved_gtid_set:接收到的 gtid 集合。

  • executed_gtid_set:已执行的 gtid 集合。

  • seconds_behind_master:SQL 线程比 IO 线程慢多少。在网络正常的情况下,可以表示从库比源库慢多少。

5.2 常见错误

主从异步复制中,存在数据库丢失的可能性,导致主从数据不一致。如果数据量比较少的情况下,我们在从库执行相关的操作补齐数据后,对改事务进行跳过。


  • 源库删除一行记录,而 slave 上找不到改行数据进行删除操作。错误代码为 1032。

  • 源库插入一行数据,而 slave 上表示改行数据早已存在,导致重复冲突。错误代码为 1062。

  • 源库上更新一行数据,而 slave 上表示找不到改行数据执行更新操作,错误代码为 1032。

5.3 主从数据校验

可以使用 GreatSQL 社区的 gt-checksum 工具对主从数据进行一致性校验,或者使用官方工具 checksum 进行数据校验。checksum 工具对数据库校验时,会给表上读锁,这一点在使用时需要注意。


gt-checksum 工具详见:https://gitee.com/GreatSQL/gt-checksum


发布于: 刚刚阅读数: 4
用户头像

GreatSQL

关注

GreatSQL社区 2023-01-31 加入

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。 社区:https://greatsql.cn/ Gitee: https://gitee.com/GreatSQL/GreatSQL

评论

发布
暂无评论
GreatSQL 异步复制及搭建_GreatSQL_InfoQ写作社区