打破黑盒子——GaussDB(DWS)导入导出业务监控方法总结

GDS、COPY、\COPY 等工具是 GaussDB(DWS) 提供的数据导入导出工具,常应用于数据迁移、数据同步、数据备份/恢复等场景。GDS 等工具在数仓日常维护中使用频率较高,难免遇到性能、功能问题,此时如果能监控到 GDS 在干什么、业务进度如何,必然能为排故提供有效参考,提高排查效率。本文从系统视图、运行日志两个方面介绍导入导出的监控方法,并配合实例进行说明,最后简要介绍 PostgreSQL 14 的 COPY 监控视图进行简单对比。

1. 视图

目前主要有2类系统视图可以对 GDS 业务进行不同角度的实时监控:

  • backend状态
  • 业务执行状态

下面分别对这两类视图进行解释说明。

1.1 backend 状态

通过系统视图 pg_stat_activity、pgxc_thread_wait_status,可以获知导入/导出backend线程的执行状态,如:是否 hang、是否死锁等。
pg_stat_activity 一般会过滤 state 使用,通过在查询结果中寻找相应的 query,对所在记录进行观察分析。

select * from pg_stat_activity where state = 'active';

查询结果类似下图,图中红框框住的是刚刚发起 GDS 导入业务。
image.png

pg_stat_activity 视图提供信息有限,可与视图 pgxc_thread_wait_status 进行关联查询等待状况,确认是否存在hang以及hang的直接原因:

select wait.*, stat.query, stat.state, stat.query_start from pgxc_thread_wait_status wait inner join pg_stat_activity stat on wait.tid = stat.pid;

查询结果类似下图,图中红框框住的是刚刚发起GDS导入业务,wait_status 列的内容是“wait node(total 3): datanode3”,表示CN此刻等待的节点共有3个,其中一个是datanode3。这个结果是与测试环境1CN 3DN一致的。
image.png

1.2 业务执行状态

2021年4月发布的 GaussDB(DWS) 8.1.1 开始提供导入导出实时监控视图:pg_bulkload_statistics、pgxc_bulkload_statistics、pgxc_bulkload_progress,支持对GDS、COPY、\COPY的实时监控。与既有约定一致,pgxc_bulkload_statistics、pgxc_bulkload_progress 是在 CN 上查询,用于获取整个集群的导入导出业务的实时状况,pg_bulkload_statistics 可在各节点上执行,用于获取当前节点的导入导出业务的实时状况。注意,这类视图需要有系统管理员权限才可以访问。

pg_bulkload_statistics、pgxc_bulkload_statistics 视图字段一样,详细说明见下表。

字段名称 字段类型 字段说明
node_name text 节点名称
db_name text 数据库名称
query_id bigint 查询ID
tid bigint 当前线程的线程号
lwtid integer 当前线程的轻量级线程号
session_id bigint GDS的会话ID
direction text 业务类型,取值包括:gds to file、gds from file、gds to pipe、gds from pipe、copy from、copy to。
query text 查询语句
address text 当前导入/导出外表的location
query_start timestamp 导入/导出开始时间
total_bytes bigint 待处理数据的总大小。仅GDS普通文件导入时,且该行记录来自CN节点才会显示,否则为空。
phase text 当前业务阶段,包括: INITIALIZING(初始化)、TRANSFER_DATA(传输中)、RELEASE_RESOURCE(结束)。
done_lines bigint 已传输行数
done_bytes bigint 已传输字节数

pgxc_bulkload_progress 视图只可用于GDS普通文件导入业务场景,本质上是基于 pgxc_bulkload_statistics 视图的聚合结果,其字段说明如下:

字段名称 字段类型 字段说明
session_id bigint GDS的会话ID
query_id bigint 查询ID
query text 查询语句
progress text 业务进度百分比

这类视图可以直接使用,或按需使用字段过滤,或者关联其他表/视图进行查询。
查询集群级导入导出的场景举例:

-- 查询集群所有的导入导出业务实时状况
select * from pgxc_bulkload_statistics;

-- 查询集群导入业务的实时进度
select * from pgxc_bulkload_progress;

-- 另外,也可以基于这类视图进行适当的计算,如计算各 DN 传输速率:
select node_name, query, round(done_bytes / 1024 / extract(epoch from(current_timestamp - query_start)), 2) || 'kB/S' as avg_speed  from  pgxc_bulkload_statistics;

-- 计算总导入/导出速率:
with trans_bytes as (select query_id, query, sum(done_bytes) as total_bytes from pgxc_bulkload_statistics group by (query_id,query)) select trans_bytes.*, stat.query_start, round(total_bytes / 1024 / extract(epoch from(current_timestamp - stat.query_start)), 2)  || 'kB/S' as speed   from trans_bytes, pg_stat_activity as stat where trans_bytes.query_id = stat.query_id;

以上样例的执行效果如图:
image.png

查询节点级导入导出业务的场景举例:

-- 查询当前节点的导入导出业务的实时进度
select * from pg_bulkload_statistics;

-- 与pg_thread_wait_status关联查询,查看是否有hang
select stat.*, wait.wait_status, wait.wait_event from pg_bulkload_statistics stat join  pg_thread_wait_status wait on stat.tid = wait.tid;

以上样例的执行效果如图:
image.png

2. 日志

导入导出业务会在不同的执行阶段向运行日志中写入业务状态记录,所以我们也可以通过日志查看执行状况。但是由于获取日志的不便性,以及分析日志的滞后性,日志获取状况是最最最后的方法,我们推荐实时视图作为导入导出监控的首选方法。

2.1 CN/DN 日志

根据业务的不同阶段和类型,打印日志内容如下表所示:

初始化阶段 数据传输阶段 结束阶段
gds import session XXXXX gds import is in the INITIALIZING state. sesssion: XXXXX gds import is transforming from INITIALIZING to TRANSFER_DATA state. Session XXXXX gds import has transformed from TRANSFER_DATA to RELEASE_RESOURCE state.
gds export session: XXXXX gds export is in the INITIALIZING state. session: XXXXX gds export is transforming from INITIALIZING to TRANSFER_DATA state. Session XXXXX gds export has transformed TRANSFER_DATA to RELEASE_RESOURCE state.
copy from copy from is in the INITIALIZING state. copy from is transforming from INITIALIZING to TRANSFER_DATA state. copy from has transformed from TRANSFER_DATA to RELEASE_RESOURCE state.
copy to copy to is in the INITIALIZING of state. copy to is transforming from INITIALIZING to TRANSFER_DATA state. copy to has transformed from TRANSFER_DATA to RELEASE_RESOURCE state.

2.2 GDS 日志

GDS 通过设置启动参数 --debug-level 可以控制打印日志级别。GDS 在关键环节上也有日志打印,如下列出的日志内容是比较重要的日志,默认日志级别可见:
(1)CN/DN 与 GDS 建连时:

关键内容: [HandleAccept] "ip:port" connected to GDS, fd is xxx, ptr is xxx
日志示例: 2021-07-30 16:24:08.274 72442 MT LOG:  [HandleAccept] "127.0.0.1:58570" connected to GDS, fd is 4, ptr is 0xfc95d0

(2)CN/DN 将要关闭连接时(只有导出业务才会有,一般是先打印DN相关的关闭信息,最后是 CN):

关键内容: Session  XXXX close connection in HandleRead. addr: ip:port, conn ptr is xxx
日志示例:2021-07-31 10:34:42.345 3478 WT LOG:  Session  81627743246173930 close connection in HandleRead. addr: 127.0.0.1:46600, conn ptr is 0xfc7bc0

(3)CN/DN关闭连接时:

关键内容:xxx closed. Event: READING/WRITING
日志示例:2021-07-30 16:24:36.208 3478 WT LOG:  Session: 81627743246142387 HandleError Node: datanode1 IP: 127.0.0.1:58580, fd is 17, connect ptr is 0xfc81b0 closed. Event: READING

(4)主线程成功把工作分配给工作线程:

关键内容:Session xxx is being transfered to worker.
日志示例:2021-07-30 16:30:06.148 72442 MT LOG:  Session 81627743246142569 is being transfered to worker.

3. 结合实例,学以致用

3.1 例1:发现copy性能瓶颈

在 COPY 导出的时候,执行视图发现同一时刻只有1个DN的传输量在增加,表明是CN是阻塞地只接收某一DN到结束,然后才开始接收下一个DN数据,存在性能问题,说明copy有较大优化空间,可以尝试使用并行读取提高性能。
image.png

3.2 例2:区分是执行慢还是hang

某测试集群执行 GDS 业务比平常慢很多,耗时很长仍没有结束,怀疑是 GDS hang 住。通过查询导入导出视图发现传输数据是在缓慢增加的,进一步查看发现此刻集群上有其他导入导出业务在运行,此时集群已经承压较大,业务缓慢是正常现象,由此自证清白,排除了 hang 问题。

4. 知识扩展:PostgreSQL是怎么做的?

PostgreSQL 14 之前并没有专门针对导入导出业务的监控工具,如果要进行监控,只能使用 pg_stat_activity、pg_locks 等通用视图。社区也注意到了这方面的缺陷,故前不久发布的PostgreSQL 14新增了对COPY命令的实时监控视图 pg_stat_progress_copy,可监控所有正在执行的COPY命令,具体的代码提交请参考 ReportProgressOfCopyCommands

每当 COPY 运行时,pg_stat_progress_copy 视图将为当前运行 COPY 命令的每个 backend 构造一行记录。下表对视图字段进行说明:

字段名称 字段类型 字段说明
pid integer backend进程号
datid oid backend连接的database的oid
datname name backend连接的database的名字
relid oid 执行COPY命令的表的OID。如果从SELECT查询复制,则设置为0。
command text 正在运行的命令为:COPY FROM或COPY TO。
type text 用于读/写数据的IO类型:FILE, PROGRAM, PIPE(用于COPY from STDIN和COPY to STDOUT),或CALLBACK(例如在逻辑复制的初始表同步过程中使用)。
bytes_processed bigint COPY命令已经处理的字节数。
bytes_total bigint COPY FROM命令中源文件的大小,以字节为单位。如果不可用,则设置为0。
tuples_processed bigint COPY命令已经处理的元组数目。
tuples_excluded bigint 由于COPY命令的WHERE子句排除了它们而未处理的元组的数目。

以下是使用 PostgreSQL 14 Beta2 版本执行 COPY 文件导入时,查询监控视图的结果:
image.png

对比可知,GaussDB(DWS) 导入导出监控视图提供的信息更全面,包括具体文件名、query 语句、执行时间、执行阶段等关键信息,基于此可以进行较为复杂的聚合计算,提供不同的监控视角;PostgreSQL 14 相对比较简单,但其字段 tuples_excluded 可以额外刻画 WHERE 过滤掉的tuples。

image.png

(完)