跳至内容

如何对失败并显示错误消息“ERROR: canceling statement due to statement timeout”的 AWS DMS 任务进行故障排除?

3 分钟阅读
0

我正在使用 AWS Database Migration Service (AWS DMS) 将数据迁移到本地 PostgreSQL 数据库或从中迁移数据。AWS DMS 任务正常运行一段时间,然后任务失败并显示错误。我如何排查并解决这些错误?

简短描述

如果 PostgreSQL 数据库是您的迁移任务的源,则 AWS DMS 会在完全加载阶段从表中获取数据。然后,AWS DMS 读取在变更数据捕获 (CDC) 阶段由复制槽保存的预写日志 (WAL)。

如果 PostgreSQL 数据库是目标,则 AWS DMS 会从源中获取数据并在复制实例中创建 CSV 文件。然后,AWS DMS 运行 COPY 命令,在完全加载阶段将这些记录插入到目标中。

但是,在 CDC 阶段,AWS DMS 在事务应用模式下运行来自源 WAL 日志的确切 DML 语句。对于批量应用模式,AWS DMS 还会在 CDC 阶段创建 CSV 文件。然后,它会运行 COPY 命令,将净变更插入到目标中。

当 AWS DMS 尝试从源获取数据或将数据放入目标中时,它使用 60 秒的默认超时设置。如果源或目标负载过重或者表中存在锁定,则 AWS DMS 无法在 60 秒内完成这些命令的运行。因此,该任务失败并显示错误“canceling statement due to statement timeout”,您会在日志中看到以下条目之一:

消息:

“]E: RetCode: SQL_ERROR SqlState: 57014 NativeError: 1 Message: ERROR: canceling statement due to statement timeout; Error while executing the query [1022502] (ar_odbc_stmt.c:2738)”

“]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392))”

要排查和解决这些错误,请执行以下步骤:

  • 确定命令运行时间长的原因。
  • 增加超时值并检查槽创建超时值。
  • 对槽创建问题进行故障排除。

解决方法

确定命令运行时间长的原因

要查找在超时期间未能运行的命令,请查看 AWS DMS 任务日志和任务的表统计数据部分。如果将参数 log_min_error_statement 设置为 ERROR 或更低的严重性,您也可以在 PostgreSQL 错误日志文件中找到这些信息。确定失败的命令后,您可以找到失败的表名。请参阅 PostgreSQL 错误日志中的以下错误消息示例:

ERROR: canceling statement due to statement timeout
STATEMENT: <The statement executed>"

要查找关联表上的锁定,请在源或目标中运行以下命令(取决于错误出现的位置):

SELECT blocked_locks.pid AS blocked_pid,
 blocked_activity.usename AS blocked_user,
 blocking_locks.pid AS blocking_pid,
         blocking_activity.usename AS blocking_user,
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

如果发现任何被阻塞的 PID,请通过运行以下命令来停止或终止该 PID:

SELECT pg_terminate_backend(blocking_pid);

由于死行或“元组”会增加 SELECT 时间,因此请通过运行以下命令来检查源表中是否存在大量死行:

select * from pg_stat_user_tables where relname= 'table_name';

检查失败的目标表是否有主键或唯一索引。如果该表没有主键或唯一索引,则在运行任何 UPDATE 语句期间都会执行全表扫描。此表扫描可能需要很长时间。

增加超时值

AWS DMS 在源端点和目标端点中都使用 executeTimeout 额外连接属性。executeTimeout 的默认值为 60 秒,因此,如果查询的运行时间超过 60 秒,AWS DMS 会超时。

如果错误出现在 Source_UnloadSource_Capture 中,请在源中设置 executeTimeout 的超时值。如果错误出现在 Target_LoadTarget_Apply 中,请在目标中设置 executeTimeout 的超时值。按照以下步骤增加超时值设置:

1.打开 AWS DMS 控制台

2.从导航窗格中选择 Endpoints(端点)。

3.选择 PostgreSQL 端点。

4.选择 Actions(操作),然后选择 Modify(修改)。

5.展开 Endpoint-specific settings(Endpoint 特定设置)部分。

6.在 Extra connection attributes(额外连接属性)字段中,输入以下值:

executeTimeout=3600;

7.选择保存

8.在 Endpoints(端点)窗格中,选择您的 PostgreSQL 端点的名称。

9.在 Connections(连接)部分中,端点的 Status(状态)由 Testing(正在测试)更改为 Successful(成功)。

您可以(以毫秒为单位)增加 PostgreSQL 数据库实例中的 statement_timeout 参数。默认值为 0,这将关闭任何查询的超时时间。您也可以增加 lock_timeout 参数。默认值为 0,这将关闭锁定超时时间。

对槽创建问题进行故障排除

如果在 PostgreSQL 数据库中创建复制槽时出现超时,则会看到类似于以下内容的日志条目:

消息

“]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392)”

您可以通过在 Task settings(任务设置)部分配置 TransactionConsistencyTimeout 参数来增加此超时时间。默认值为 600 秒。

如果数据库用户表中有任何活动锁定,则 PostgreSQL 无法创建复制槽。通过运行以下命令检查锁定:

select * from pg_locks;

然后,要测试错误是否已解决,请运行以下命令在源 PostgreSQL 数据库中手动创建复制槽:

select  xlog_position FROM pg_create_logical_replication_slot('<Slot name as per
    the task log>', 'test_decoding');

如果命令仍然无法创建槽,则您可能需要使用 PostgreSQL DBA 来确定瓶颈并配置数据库。如果命令成功,请删除您刚刚作为测试创建的槽:

select pg_drop_replication_slot(‘<slot name>');

最后,重启迁移任务。


相关信息

PostgreSQL documentation for client connection defaults(有关客户端连接默认值的 PostgreSQL 文档)

使用 PostgreSQL 作为 AWS DMS 目标时的额外连接属性

使用 PostgreSQL 作为 DMS 源时的额外连接属性

使用 PostgreSQL 数据库作为 AWS DMS 源