注:本文不是讲解Db2 Activity event monitor,只是一个用法实践。要了解Activity event monitor,请参考 https://www.ibm.com/docs/en/db2/11.5?topic=events-activity-event-monitoring 。
环境
- Red Hat Enterprise Linux release 8.8 (Ootpa)
- Db2 MPP V2 11.5.8
准备
Activity event monitor
在Db2中创建一个Activity event monitor(其table所在的table space跨所有DB member):
sql
create event monitor <XXX> for activities write to table
activity (table IBM_RTMON.activity_<timestamp>)
, activitystmt (table IBM_RTMON.activity_stmt_<timestamp>)
, activitymetrics (table IBM_RTMON.activity_metrics_<timestamp>)
manualstart
其中:
activity:包含event信息activity_stmt:包含statement信息activity_metrics:包含metrics信息,如ROWS_INSERTED
将其激活:
sql
set event monitor <XXX> state 1
Table
创建table T1 和 T2 :
sql
create table bluadmin.t1(c1 int, c2 int);
sql
create table bluadmin.t2(c1 int, c2 int);
向 T1 插入一些数据。
powershell
[db2inst1@dashmpp-head-0 - Db2wh ~]$ db2 "select count(*) from bluadmin.t1"
1
---------------------------------
160.
1 record(s) selected.
Workload
假设对 T1 和 T2 的DML操作都属于 SYSDEFAULTUSERWORKLOAD workload。
Alter workload SYSDEFAULTUSERWORKLOAD :
sql
alter workload SYSDEFAULTUSERWORKLOAD COLLECT ACTIVITY DATA ON COORDINATOR MEMBER WITH DETAILS
注:默认情况下,workload的activity不会被Activity event monitor收集。
可以查看 syscat.workloads 视图:
powershell
[db2inst1@dashmpp-head-0 - Db2wh ~]$ db2 "select workloadid, cast(workloadname as varchar(30)) as workloadname, collectactdata, collectactpartition from syscat.workloads order by workloadid"
WORKLOADID WORKLOADNAME COLLECTACTDATA COLLECTACTPARTITION
----------- ------------------------------ -------------- -------------------
1 SYSDEFAULTUSERWORKLOAD D C
2 SYSDEFAULTADMWORKLOAD D C
3 DSM_WORKLOAD N C
4 CONSOLE_WORKLOAD N C
5 WL_0 D C
6 WL_1 D C
......
对 COLLECTACTDATA 和 COLLECTACTPARTITION 的解释,详见 https://www.ibm.com/docs/en/db2/11.5?topic=views-syscatworkloads 。
问题
清空表 T2 ,然后将 T1 的数据插入 T2 :
sql
insert into bluadmin.t2 (select * from bluadmin.t1)
Activity event monitor会产生一个event,并在相应的table里产生一些数据。
先来看看 activity_stmt 表:
sql
select partition_number, stmt_text, *
from ibm_rtmon.activity_stmt_1701671110833
where cast(stmt_text as varchar(100)) like 'insert into t2%';
注意:这里 like 条件不要写成 '%insert into t2%' ,否则把其它无关SQL(比如本条SQL也包含 insert into t2 )也查到了。
说明已经产生event了,然后再根据其信息比如 appl_id 来查找 activity_metrics 表:
sql
select partition_number, rows_inserted, *
from ibm_rtmon.activity_metrics_<timestamp>
where appl_id = '<XXXXXX>'
在结果中只有1条记录,其 partition_number 为0,而 rows_inserted 也是0。

明明插入了160条记录,怎么在Activity event monitor产生的event里, rows_inserted 是0呢?
分析
这是因为,workload SYSDEFAULTUSERWORKLOAD 的 collectactpartition 是 C ,也就是 ON COORDINATOR MEMBER ,所以 activity_metrics 表只产生了coordinator member所对应的那条记录,而在此member上实际并没有插入数据,所以 rows_inserted 是0。
解决方法
把workload SYSDEFAULTUSERWORKLOAD 的 collectactpartition 改为 D ,也就是 ON ALL MEMBERS :
sql
alter workload SYSDEFAULTUSERWORKLOAD COLLECT ACTIVITY DATA ON ALL MEMBERS WITH DETAILS
然后查看 syscat.workloads ,确认修改成功:
powershell
[db2inst1@dashmpp-head-0 - Db2wh ~]$ db2 "select workloadid, cast(workloadname as varchar(30)) as workloadname, collectactdata, collectactpartition from syscat.workloads where workloadid = 1"
WORKLOADID WORKLOADNAME COLLECTACTDATA COLLECTACTPARTITION
----------- ------------------------------ -------------- -------------------
1 SYSDEFAULTUSERWORKLOAD D D
1 record(s) selected.
现在,将 T2 表清空,再重新插入一些数据,这回在 activity_metrics 表里就会产生多条记录:

把各个member的 rows_inserted 值加起来,正好等于插入的数据总数160。
可见,要用 activity_metrics 表收集metrics,需要将对应的workload设置为 COLLECT ACTIVITY DATA ON ALL MEMBERS ,不能是 COLLECT ACTIVITY DATA ON COORDINATOR MEMBER ,否则只能收集到coordinator member上的metric。
其它
对于一条插入语句:
- 若workload指定为
COLLECT ACTIVITY DATA ON COORDINATOR MEMBER,则activity、activity_stmt、activity_metrics都只产生一条记录。 - 若workload指定为
COLLECT ACTIVITY DATA ON ALL MEMBERS,则activity和activity_metrics会产生多条记录,每个member对应一条记录。而activity_stmt只产生一条记录。
要收集 rows_inserted 信息,就要把workload指定为 COLLECT ACTIVITY DATA ON ALL MEMBERS ,同时,不能以 partition_number 作为三个table的连接条件。
正确做法是:
- 如果只想要总的信息,则先把
activity_metrics表里各个member的rows_inserted信息汇总起来,再和其它表join - 如果要看各个member的详细信息,则收集
activity_metrics表里各个member的rows_inserted信息,再和其它表join
总之不要以 partition_number 作为和 activity_stmt table的连接条件,而只以 appl_id 、 uow_id 、 activity_id 、 activity_secondary_id 作为连接条件。比如:
sql
with m as (select appl_id, uow_id, activity_id, activity_secondary_id, sum(rows_inserted) as rows_inserted
from ibm_rtmon.activity_metrics_<timestamp>
group by appl_id, uow_id, activity_id, activity_secondary_id)
select s.stmt_text, m.rows_inserted
from ibm_rtmon.activity_<timestamp> a
join ibm_rtmon.activity_stmt_<timestamp> s
on a.appl_id = s.appl_id and a.uow_id = s.uow_id and a.activity_id = s.activity_id and a.activity_secondary_id = s.activity_secondary_id
join m
on a.appl_id = m.appl_id and a.uow_id = m.uow_id and a.activity_id = m.activity_id and a.activity_secondary_id = m.activity_secondary_id
运行结果如下:

activity 表的 details_xml 字段
activity 表有一个 details_xml 字段,里面包含了很多信息,比如 rows_inserted 。把workload设置为 COLLECT ACTIVITY DATA ON ALL MEMBERS ,activity 表会为每个member产生一条记录,然后也可以从 details_xml 字段获取 rows_inserted ,每个member上获取的是各自的 rows_inserted 值。例如:
sql
select a.partition_number, s.stmt_text, xml.rows_inserted from ibm_rtmon.activity_<timestamp> a
join ibm_rtmon.activity_stmt_<timestamp> s
on a.appl_id = s.appl_id and a.uow_id = s.uow_id and a.activity_id = s.activity_id and a.activity_secondary_id = s.activity_secondary_id
, XMLTABLE
(
XMLNAMESPACES( default 'http://www.ibm.com/xmlns/prod/db2/mon' ),
'$metrics/activity_metrics' PASSING XMLPARSE( DOCUMENT a.details_xml ) as "metrics" COLUMNS
ROWS_INSERTED BIGINT PATH'rows_inserted'
) as xml
where stmt_text like 'insert into t2%';

可见,各个member上的 rows_inserted 总和也是160。
参考
https://www.ibm.com/docs/en/db2/11.5?topic=views-syscatworkloadshttps://www.ibm.com/docs/en/db2/11.5?topic=statements-alter-workload#sdx-synid_alter-collect-activity-data-clausehttps://www.ibm.com/docs/en/db2/11.5?topic=events-activity-event-monitoring