### 17.4.11 延迟复制

[](<>)[](<>)[](<>)[](<>)

MySQL 支持延迟复制，这样副本服务器会故意比源服务器晚至少指定时间执行事务。本节介绍如何在副本上配置复制延迟，以及如何监控复制延迟。

在 MySQL 8.0 中，延迟复制的方法取决于两个时间戳，`immediate_commit_timestamp`和`original_commit_timestamp`（看[复制延迟时间戳](replication-delayed.html#replication-delayed-timestamps)）。如果复制拓扑中的所有服务器都运行 MySQL 8.0 或更高版本，则使用这些时间戳测量延迟复制。如果直接源或副本没有使用这些时间戳，则使用 MySQL 5.7 的延迟复制实现（参见[延迟复制](https://dev.mysql.com/doc/refman/5.7/en/replication-delayed.html)）。本节描述了所有使用这些时间戳的服务器之间的延迟复制。

默认复制延迟为 0 秒。用一个[`将复制源更改为 SOURCE_DELAY=*`ñ`*`](change-replication-source-to.html)语句（来自 MySQL 8.0.23）或`将 MASTER 更改为 MASTER_DELAY=*`ñ`*`语句（在 MySQL 8.0.23 之前）将延迟设置为*`ñ`*秒。从源接收到的事务至少要到*`ñ`*比它在直接源上的提交晚几秒钟。延迟发生在每个事务（不是以前的 MySQL 版本中的事件），实际延迟仅施加在`gtid_log_event`要么`匿名_gtid_log_event`.事务中的其他事件始终跟随这些事件，而无需对其施加任何等待时间。

笔记

[`开始复制`](start-replica.html)和[`停止复制`](stop-replica.html)立即生效并忽略任何延迟。[`重置副本`](reset-replica.html)将延迟重置为 0。

这[`复制应用程序配置`](performance-schema-replication-applier-configuration-table.html)性能模式表包含`DESIRED_DELAY`列显示使用配置的延迟`SOURCE_DELAY`\|`MASTER_DELAY`选项。这[`复制应用程序状态`](performance-schema-replication-applier-status-table.html)性能模式表包含`REMAINING_DELAY`显示剩余延迟秒数的列。

延迟复制可用于多种用途：

-   防止用户在源上出错。通过延迟，您可以将延迟的副本回滚到错误之前的时间。

-   测试存在滞后时系统的行为。例如，在应用程序中，延迟可能是由副本上的负载过重引起的。但是，生成此负载级别可能很困难。延迟复制可以模拟延迟，而无需模拟负载。它还可用于调试与滞后副本相关的条件。

-   检查数据库过去的样子，而无需重新加载备份。例如，通过配置延迟一周的副本，如果您需要查看数据库在最后几天的开发价值之前的样子，则可以检查延迟的副本。

#### 复制延迟时间戳

MySQL 8.0 提供了一种新方法来测量复制拓扑中的延迟（也称为复制滞后），该方法取决于与写入二进制日志的每个事务（而不是每个事件）的 GTID 关联的以下时间戳。

-   `original_commit_timestamp`：事务被写入（提交）到原始源的二进制日志的纪元以来的微秒数。

-   `immediate_commit_timestamp`: 事务被写入（提交）到直接源的二进制日志的纪元以来的微秒数。

    的输出[**mysqlbinlog**](mysqlbinlog.html)以两种格式显示这些时间戳，从纪元开始的微秒以及`时间戳`格式，基于用户定义的时区以提高可读性。例如：


```
#170404 10:48:05 server id 1  end_log_pos 233 CRC32 0x016ce647     GTID    last_committed=0
\ sequence_number=1    original_committed_timestamp=1491299285661130    immediate_commit_timestamp=1491299285843771
# original_commit_timestamp=1491299285661130 (2017-04-04 10:48:05.661130 WEST)
# immediate_commit_timestamp=1491299285843771 (2017-04-04 10:48:05.843771 WEST)
 /*!80001 SET @@SESSION.original_commit_timestamp=1491299285661130*//*!*/;
   SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'/*!*/;
# at 233
```

作为一项规则，`original_commit_timestamp`在应用事务的所有副本上始终相同。在源-副本复制中，`original_commit_timestamp`（原始）源的二进制日志中的事务总是与其相同`immediate_commit_timestamp`.在副本的中继日志中，`original_commit_timestamp`和`immediate_commit_timestamp`事务与源的二进制日志中的相同；而在它自己的二进制日志中，事务的`immediate_commit_timestamp`对应于副本提交事务的时间。

在组复制设置中，当原始源是组的成员时，`original_commit_timestamp`当事务准备好提交时生成。换句话说，当它在原始源上完成执行并且其写入集准备好发送给组的所有成员以进行认证时。当原始源是组外的服务器时，`original_commit_timestamp`被保留。相同`original_commit_timestamp`对于特定事务，将复制到组中的所有服务器，以及从成员复制的组外的任何副本。从 MySQL 8.0.26 开始，事务的每个接收者还将本地提交时间存储在其二进制日志中，使用`immediate_commit_timestamp`.

组复制独有的视图更改事件是一种特殊情况。包含这些事件的事务由每个组成员生成，但共享相同的 GTID（因此，它们不是首先在源中执行然后复制到组，而是组的所有成员执行并应用相同的事务）。在 MySQL 8.0.26 之前，这些事务有它们的`original_commit_timestamp`设置为零，并且它们以这种方式出现在可见输出中。从 MySQL 8.0.26 开始，为了提高可观察性，组成员为与视图更改事件关联的事务设置本地时间戳值。

#### 监控复制延迟

在以前的 MySQL 版本中监控复制延迟（滞后）的最常见方法之一是依靠`Seconds_Behind_Master`输出中的字段`显示副本状态`.但是，当使用比传统源-副本设置更复杂的复制拓扑时，此指标不适合，例如组复制。添加的`immediate_commit_timestamp`和`original_commit_timestamp`MySQL 8 提供了关于复制延迟的更精细程度的信息。在支持这些时间戳的拓扑中监控复制延迟的推荐方法是使用以下性能模式表。

-   [`复制连接状态`](performance-schema-replication-connection-status-table.html)：与源的连接的当前状态，提供有关连接线程排队到中继日志中的最后和当前事务的信息。

-   [`replication_applier_status_by_coordinator`](performance-schema-replication-applier-status-by-coordinator-table.html)：协调器线程的当前状态，仅在使用多线程副本时显示信息，提供有关协调器线程缓冲到工作队列的最后一个事务的信息，以及它当前正在缓冲的事务。

-   [`replication_applier_status_by_worker`](performance-schema-replication-applier-status-by-worker-table.html)：应用从源接收的事务的线程的当前状态，提供有关复制 SQL 线程或使用多线程副本时每个工作线程应用的事务的信息。

    使用这些表，您可以监视有关相应线程处理的最后一个事务以及该线程当前正在处理的事务的信息。该信息包括：

-   交易的 GTID

-   一笔交易的`original_commit_timestamp`和`immediate_commit_timestamp`，从副本的中继日志中检索

-   线程开始处理事务的时间

-   对于最后处理的事务，线程完成处理它的时间

    除了性能模式表，输出[`显示副本状态`](show-replica-status.html)有三个字段显示：

-   `SQL_延迟`：一个非负整数，指示使用配置的复制延迟[`将复制源更改为 SOURCE_DELAY=*`ñ`*`](change-replication-source-to.html)（来自 MySQL 8.0.23）或`将 MASTER 更改为 MASTER_DELAY=N`（在 MySQL 8.0.23 之前），以秒为单位。

-   `SQL_Remaining_Delay`： 什么时候`Replica_SQL_Running_State`是`等到主执行事件后的 MASTER_DELAY 秒`，该字段包含一个整数，表示延迟的剩余秒数。在其他时候，这个字段是`空值`.

-   `Replica_SQL_Running_State`: 表示 SQL 线程状态的字符串（类似于`Replica_IO_State`）。该值与`状态`SQL 线程的值，由[`显示进程列表`](show-processlist.html).

    当复制 SQL 线程在执行事件之前等待延迟过去时，[`显示进程列表`](show-processlist.html)显示其`状态`价值为`等到主执行事件后的 MASTER_DELAY 秒`.
