使用Prometheus + Grafana监控Oracle Transactional Event Queues
首先
在Oracle Database 23c(21c)中,有两个免费可用的功能,一个是功能强大的消息队列系统Advanced Queuing(AQ),另一个是可以实现高吞吐量消息交换的Transactional Event Queues(TxEventQ)。本次我们想要构建一个用于监控性能的TxEventQ Monitor系统来使用这些功能。有关TxEventQ的详细信息,请参考此处的文档或以下的Qiita文章。
组件包括以下三个部分。
Oracle Database Observability Exporter: Oracle Database用のPrometheusエクスポータ。データベースに接続し、メトリックを問い合せて、メトリックをPrometheus様式のメトリックに書式化します。
Prometheus: 監視システムおよび時系列データベース。Oracle DBエクスポータから収集したメトリックを時系列形式で管理します。
Grafana: 分析およびインタラクティブな視覚化プラットフォーム。データ・ソースとしてPrometheusを指定します。
文件在这里。

环境信息
构建监视框架的虚拟机信息
-
- シェイプ: VM.Standard.E4.Flex
-
- イメージ: Oracle Linux 8.8
-
- Docker: 24.0.7
- Docker Compose: 2.21.0
被监视的Oracle数据库
- Oracle Database 23.3(OCIのBaseDB)
创建监视用数据库用户
这次我们在OCI上创建了一个23c(23.3)的BaseDB,并在其上面创建了一个名为pdb23c的PDB。我们将其作为监视对象的PDB,并在其中创建了一个名为monitor的数据库用户用于监视。
-
- 使用SYS创建用户
-
- 通过授予SELECT_CATALOG_ROLE角色,您可以获得在Prometheus中收集度量的目录等参考权限。
-
- create user monitor identified by Welcome12345#;
-
- grant connect, resource, DBA, SELECT_CATALOG_ROLE, unlimited tablespace to monitor;
授予TxEventQ相关角色
grant execute on dbms_aq to monitor;
grant execute on dbms_aqadm to monitor;
grant execute on dbms_aqin to monitor;
grant execute on dbms_aqjms_internal to monitor;
grant execute on dbms_teqk to monitor;
grant execute on DBMS_RESOURCE_MANAGER to monitor;
grant select on sys.aq$_queue_shards to monitor;
grant select on user_queue_partition_assignment_table to monitor;
从虚拟机使用SQL*Plus连接到pdb23c进行监测(简易连接)
sqlplus monitor/Welcome12345#@xxxx:1521/pdb23c.xxxx.vcn1.oraclevcn.com
SQL*Plus: Release 21.0.0.0.0 – Production on Tue Nov 14 06:26:35 2023
Version 21.9.0.0.0
Copyright (c) 1982, 2022, Oracle. All rights reserved.
上次成功登录时间: Tue Nov 14 2023 06:26:23 +00:00
已连接到:
Oracle Database 23c Enterprise Edition Release 23.0.0.0.0 – Production
Version 23.3.0.23.09
Oracle数据库可观察性导出器的设置。
Oracle数据库可观测性导出程序可使用可从Oracle容器注册表下载的容器映像在本地容器中使用。不需要进行身份验证或许可证明/批准。
顺便说一下,这个Oracle容器注册表中还包含了Autonomous Database的免费映像以及适用于微服务的Oracle交易管理器(MicroTx)的映像。
-
- 创建作业目录
-
- mkdir -p monitoring/exporter
-
- cd monitoring/exporter
创建自定义指标配置文件txeventq-metrics.toml
这次除了默认的指标之外,我们还想收集TxEventQ的指标,所以我们需要创建一个toml文件,并使用该文件来创建Docker镜像。
txeventq-metrics.toml
[[metric]]
context = “ownership”
metricsdesc = { inst_id = “当前队列的所有者实例ID。” }
request = ”’
SELECT
inst_id
FROM
gv$persistent_queues
WHERE
ROWNUM < 2
”’
[[metric]]
context = “teq”
metricsdesc = { curr_inst_id = “当前实例的ID” }
request = “SELECT instance_number AS curr_inst_id FROM v$instance”
[[metric]]
context = “teq”
labels = [“inst_id”]
metricsdesc = { total_queues = “队列的总数” }
request = ”’
SELECT
inst_id,
COUNT(*) AS total_queues
FROM
(
SELECT DISTINCT
t1.inst_id,
t2.queue_name
FROM
gv$aq_sharded_subscriber_stat t1
JOIN gv$persistent_queues t2 ON t1.queue_id = t2.queue_id
)
GROUP BY
inst_id
”’
[[metric]]
context = “teq”
labels = [“inst_id”]
metricsdesc = { total_subscribers = “订阅者的总数” }
request = ”’
SELECT
inst_id,
COUNT(*) AS total_subscribers
FROM
(
SELECT DISTINCT
inst_id,
subscriber_id
FROM
gv$aq_sharded_subscriber_stat
)
GROUP BY
inst_id
”’
[[metric]]
context = “teq”
labels = [“inst_id”, “queue_name”, “subscriber_name”]
metricsdesc = { enqueued_msgs = “入队消息的总数。”, dequeued_msgs = “出队消息的总数。”, remained_msgs = “剩余消息的总数。”, time_since_last_dequeue = “自上次出队以来的时间。”, estd_time_to_drain_no_enq = “如果没有入队,排空的预计时间。”, message_latency_1 = “过去5分钟的消息延迟。”, message_latency_2 = “过去1小时的消息延迟。”, message_latency_3 = “过去5个小时的消息延迟。” }
request = ”’
SELECT DISTINCT
t1.inst_id,
t1.queue_id,
t2.queue_name,
t1.subscriber_id AS subscriber_name,
t1.enqueued_msgs,
t1.dequeued_msgs,
t1.remained_msgs,
t1.time_since_last_dequeue,
t1.estd_time_to_drain_no_enq,
t1.message_latency_1,
t1.message_latency_2,
t1.message_latency_3
FROM
(
SELECT
inst_id,
queue_id,
subscriber_id,
SUM(enqueued_msgs) AS enqueued_msgs,
SUM(dequeued_msgs) AS dequeued_msgs,
SUM(enqueued_msgs – dequeued_msgs) AS remained_msgs,
MIN(time_since_last_dequeue) AS time_since_last_dequeue,
MAX(estd_time_to_drain_no_enq) AS estd_time_to_drain_no_enq,
AVG(10) AS message_latency_1,
AVG(20) AS message_latency_2,
AVG(30) AS message_latency_3
FROM
gv$aq_sharded_subscriber_stat
GROUP BY
queue_id,
subscriber_id,
inst_id
) t1
JOIN gv$persistent_queues t2 ON t1.queue_id = t2.queue_id
”’
Dockerfile
FROM container-registry.oracle.com/database/observability-exporter:1.1.0
COPY txeventq-metrics.toml /
ENTRYPOINT [“/oracledb_exporter”, “–custom.metrics”, “/txeventq-metrics.toml”]
构建
docker build -t txeventq_exporter:1.0 .
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
txeventq_exporter 1.0 8169e80d23bb 12 minutes ago 709MB
运行测试
docker run -it –rm –name exporter -e DB_USERNAME=MONITOR -e DB_PASSWORD=Welcome12345# -e DB_CONNECT_STRING=xxxx:1521/pdb23c.xxxx.vcn1.oraclevcn.com -p 9161:9161 txeventq_exporter:1.0
在本地(http://localhost:9161/metrics)中确认
# HELP oracledb_up Oracle数据库服务器是否运行。
# TYPE oracledb_up gauge
oracledb_up 1
有许多指标被记录下来,但其中一个指标oracledb_up的值为1,说明已成功连接到数据库服务器。
普罗米修斯的设置
-
- 创建作业用目录
-
- mkdir -p monitoring/prometheus
-
- cd monitoring/prometheus
创建Prometheus的配置文件prometheus.yaml
prometheus.yaml
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 15s
scrape_configs:
– job_name: prometheus
honor_timestamps: true
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
static_configs:
– targets:
– localhost:9090
– job_name: oracle-exporter
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
static_configs:
– targets:
– exporter:9161
拉取Prometheus官方镜像
docker pull prom/prometheus:v2.47.2
Grafana的设置
-
- 创建作业目录
-
- mkdir monitoring/grafana
配置datasource.yaml
mkdir monitoring/grafana/datasources
datasource.yaml
apiVersion: 1
datasources:
– name: Prometheus
type: prometheus
url: http://prometheus:9090
isDefault: true
access: proxy
editable: true
配置dashboard
本次将使用两个预先创建的仪表板进行DB实例和TxEventQ的监视。在dashboards目录下,创建两个json文件oracledb.json和txeventq.json,以及一个配置文件dashboard.yaml。其中,oracledb.json使用此处的文件,txeventq.json使用此处的文件。
mkdir monitoring/grafana/dashboards
dashboard.yaml
apiVersion: 1
providers:
– name: “Dashboard provider”
orgId: 1
type: file
disableDeletion: false
updateIntervalSeconds: 10
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
拉取Grafana官方镜像
docker pull grafana/grafana:10.2.1
docker compose的配置
这次,我们使用了Docker Compose进行执行。我们将在monitoring目录中创建以下的docker-compose.yml文件。
services:
prometheus:
image: prom/prometheus:v2.47.2
container_name: prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yaml'
ports:
- 9090:9090
restart: unless-stopped
volumes:
- ./prometheus:/etc/prometheus
- prom_data:/prometheus
grafana:
image: grafana/grafana:10.2.1
container_name: grafana
ports:
- 3000:3000
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=grafana
volumes:
- ./grafana/datasources:/etc/grafana/provisioning/datasources
- ./grafana/dashboards:/var/lib/grafana/dashboards
- ./grafana/datasources/datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yaml
- ./grafana/dashboards/dashboard.yaml:/etc/grafana/provisioning/dashboards/main.yaml
exporter:
image: txeventq_exporter:1.0
container_name: exporter
ports:
- 9161:9161
environment:
- DB_USERNAME=monitor
- DB_PASSWORD=Welcome12345#
- DB_CONNECT_STRING=xxxx.vcn1.oraclevcn.com:1521/pdb23c.xxxx.vcn1.oraclevcn.com
volumes:
- ./exporter:/exporter
volumes:
prom_data:
请根据需要适当修改DB连接字符串DB_CONNECT_STRING。
最终的目录结构在这里。
[opc@devinsrd monitoring]$ tree
.
├── docker-compose.yml
├── exporter
│ ├── Dockerfile
│ └── txeventq-metrics.toml
├── grafana
│ ├── dashboards
│ │ ├── dashboard.yaml
│ │ ├── oracledb.json
│ │ └── txeventq.json
│ └── datasources
│ └── datasource.yaml
└── prometheus
└── prometheus.yaml
运行 Docker Compose。
docker compose up -d
[+] Running 5/5
✔ Network monitoring_default Created 0.2s
✔ Volume "monitoring_prom_data" Created 0.0s
✔ Container prometheus Started 0.1s
✔ Container grafana Started 0.1s
✔ Container exporter Started 0.1s
在本地(http://localhost:3000)进行确认。


-
- データベースのステータス
-
- アクティブなセッション数(Background、user)
-
- 実行数
- 待機時間

接下来,我们来监视TxEventQ。由于还没有创建队列,所以我们在下面进行创建。
declare
subscriber sys.aq$_agent;
begin
-- トピック(キュー表の作成)
dbms_aqadm.create_transactional_event_queue(
queue_name => 'my_topic',
multiple_consumers => true -- pub/subトピックの作成
);
-- トピックの開始
dbms_aqadm.start_queue(
queue_name => 'my_topic'
);
-- サブスクライバの登録
dbms_aqadm.add_subscriber(
queue_name => 'my_topic',
subscriber => sys.aq$_agent(
'my_subscriber', -- サブスクライバ名
null, -- 通知に使用されるメールアドレス
0 -- プロトコル
),
rule => 'correlation = ''my_subscriber'''
);
end;
/
如果创建失败,请检查权限。此外,dbms_aqadm.create_transactional_event_queue仅适用于Oracle Database 21c和23c。
我已经创建了一个队列表,接下来将尝试向队列表发送消息(入队)。
declare
enqueue_options dbms_aq.enqueue_options_t;
message_properties dbms_aq.message_properties_t;
message_handle raw(16);
message SYS.AQ$_JMS_TEXT_MESSAGE;
begin
-- メッセージ・ペイロードの作成
message := SYS.AQ$_JMS_TEXT_MESSAGE.construct;
message.set_text('{"orderid": 12345, "username": "Jessica Smith"}');
-- コンシューマ名の登録
message_properties.correlation := 'my_subscriber';
-- メッセージのエンキュー
dbms_aq.enqueue(
queue_name => 'my_topic',
enqueue_options => enqueue_options,
message_properties => message_properties,
payload => message,
msgid => message_handle);
-- トランザクションのコミット
commit;
end;
/
因为我们已经完成了Enqueue,所以我会在Grafana上进行确认。我会查看仪表板上的TxEventQ Monitor。
你可以通过以下指标进行确认。
-
- TxEventQのステータス
-
- キュー表(トピック)の数
-
- サブスクライバの数
-
- エンキュー/デキュー率(性能指標)
- エンキュー/デキューされたメッセージ数

另外,您还可以获取以下针对每个主题或订阅者的特定指标。

最后一句
本次我们尝试使用Oracle Database Observability Exporter + Prometheus + Grafana来监控Oracle Transactional Event Queues。虽然可以使用Enterprise Manager(EM)或云端的Database Management等服务来监控Oracle Database,但如果要对特定队列进行指标监控,则可以结合这些开源工具来实现。