Advanced Queuing Internals
Advanced Queuing Internals
Internals
Julian Dyke
Independent Consultant
Web Version - November 2008
1
juliandyke.com
Agenda
Introduction
Single Consumer Queues
Multiple Consumer Queues
Recipients
Subscribers
Exception Queues
Array Payloads
Buffered Messages
Spilled Messages
Performance
juliandyke.com
Introduction
Advanced Queuing
Advanced Queuing
Introduced in Oracle 8.0
Extended and enhanced in most subsequent versions
Supports Oracle Streams in Oracle 9.2 and above
Supports buffered messages in Oracle 10.2 and above
juliandyke.com
Introduction
Advanced Queuing
Buffered messages
Stored in SGA
Can be spilled to queue table
Lost during instance restart
juliandyke.com
Introduction
Advanced Queuing
Subscribers can:
Specify rules to control which messages they dequene
Specify transformations to be performed against dequeued data
juliandyke.com
Advanced Queuing
Introduction
juliandyke.com
Introduction
Payloads
juliandyke.com
juliandyke.com
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','RAW');
Queue table QT1 contains the following columns:
Data Type
Data Type
1 Q_NAME
VARCHAR2(30)
16
16 DEQ_TIME
TIMESTAMP(6)
2 MSG_ID
RAW(16)
17
17 DEQ_UID
VARCHAR2(30)
3 CORRID
VARCHAR2(128)
18
18 DEQ_TID
VARCHAR2(30)
4 PRIORITY
NUMBER
19
19 RETRY_COUNT
NUMBER
5 STATE
NUMBER
20
20 EXCEPTION_QSCHEMA VARCHAR2(30)
6 DELAY
TIMESTAMP(6)
21
21 EXCEPTION_QUEUE
VARCHAR2(30)
7 EXPIRATION
NUMBER
22
22 STEP_NO
NUMBER
8 TIME_MANAGER_INFO TIMESTAMP(6)
23
23 RECIPIENT_KEY
NUMBER
9 LOCAL_ORDER_NO
NUMBER
24
24 DEQUEUE_MSG_ID
RAW(16)
10
10 CHAIN_NO
NUMBER
25
25 SENDER_NAME
VARCHAR2(30)
11
11 CSCN
NUMBER
26
26 SENDER_ADDRESS
VARCHAR2(1024)
12
12 DSCN
NUMBER
27
27 SENDER_PROTOCOL
NUMBER
13
13 ENQ_TIME
TIMESTAMP(6)
28
28 USER_DATA
BLOB
14
14 ENQ_UID
VARCHAR2(30)
29
29 USER_PROP
SYS.ANYDATA
15
15 ENQ_TID
VARCHAR2(30)
juliandyke.com
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','TYPE1');
Queue table QT1 contains the following columns:
Data Type
Data Type
1 Q_NAME
VARCHAR2(30)
17
17 DEQ_UID
VARCHAR2(30)
2 MSG_ID
RAW(16)
18
18 DEQ_TID
VARCHAR2(30)
3 CORRID
VARCHAR2(128)
19
19 RETRY_COUNT
NUMBER
4 PRIORITY
NUMBER
20
20 EXCEPTION_QSCHEMA VARCHAR2(30)
5 STATE
NUMBER
21
21 EXCEPTION_QUEUE
VARCHAR2(30)
6 DELAY
TIMESTAMP(6)
22
22 STEP_NO
NUMBER
7 EXPIRATION
NUMBER
23
23 RECIPIENT_KEY
NUMBER
8 TIME_MANAGER_INFO TIMESTAMP(6)
24
24 DEQUEUE_MSG_ID
RAW(16)
9 LOCAL_ORDER_NO
NUMBER
25
25 SENDER_NAME
VARCHAR2(30)
10
10 CHAIN_NO
NUMBER
26
26 SENDER_ADDRESS
VARCHAR2(1024)
11
11 CSCN
NUMBER
27
27 SENDER_PROTOCOL
NUMBER
12
12 DSCN
NUMBER
28
28 USER_DATA
TYPE1
13
13 ENQ_TIME
TIMESTAMP(6)
28
29 SYS_NC00029$
NUMBER
14
14 ENQ_UID
VARCHAR2(30)
28
30 SYS_NC00030$
NUMBER
15
15 ENQ_TID
VARCHAR2(30)
28
31 SYS_NC00031$
NUMBER
16
16 DEQ_TIME
TIMESTAMP(6)
29
32 USER_PROP
SYS.ANYDATA
juliandyke.com
The following objects will be created (object IDs and constraint IDs will vary):
Object
ID
Object Name
Object Type
70581
QT1
TABLE
70582
SYS_LOB0000070581C00028$
$
LOB
70583
SYS_IL0000070581C00028$$
LOB INDEX
70584
SYS_LOB0000070581C00029$$
LOB
70585
SYS_IL0000070581C00029$$
LOB INDEX
70586
SYS_C009433
INDEX
70587
AQ$_QT1_T
INDEX
70588
AQ$_QT1_I
INDEX
70589
QT70581_BUFFER
VIEW
70590
AQ$QT1
VIEW
70591
AQ$_QT1_F
VIEW
70592 are
AQ$_QT1_E
QUEUE
LOB columns
used for USER_DATA and USER_PROP
columns
juliandyke.com
The following objects will be created (object IDs and constraint IDs will vary):
Object
ID
Object Name
Object Type
70581
QT1
TABLE
70582
SYS_LOB0000070581C00032$
$
LOB
70583
SYS_IL0000070581C00032$$
LOB INDEX
70584
SYS_C009433
INDEX
70585
AQ$_QT1_T
INDEX
70586
AQ$_QT1_I
INDEX
70587
QT70581_BUFFER
VIEW
70589
AQ$QT1
VIEW
70590
AQ$_QT1_F
VIEW
70591 is used
AQ$_QT1_E
LOB column
for USER_PROP columnQUEUE
juliandyke.com
The following indexes will be created by default (constraint IDs will vary):
Index Name
Column
#
Column Name
SYS_C00943
6
MSGID
AQ$_QT1_I
Q_NAME
STATE
ENQ_TIME
STEP_NO
CHAIN_NO
LOCAL_ORDER_NO
TIME_MANAGER_INF
O
AQ$_QT1_T
juliandyke.com
Column
#
enq_time
priority
priority,enq_time
enq_time,priority
Q_NAME
Q_NAME
Q_NAME
Q_NAME
STATE
STATE
STATE
STATE
ENQ_TIME
PRIORITY
PRIORITY
ENQ_TIME
STEP_NO
CHAIN_NO
ENQ_TIME
STEP_NO
CHAIN_NO
LOCAL_ORDER_N
O
STEP_NO
PRIORITY
LOCAL_ORDER_N
O
CHAIN_NO
CHAIN_NO
juliandyke.com
LOCAL_ORDER_N
LOCAL_ORDER_N
QT<object_id>_BUFFER
e.g. QT70581_BUFFER
based on X$BUFFER2
AQ$_<queue_table_name>_F
e,g. AQ$_QT1_F
based on QT1 and ALL_DEQUEUE_QUEUES
juliandyke.com
juliandyke.com
juliandyke.com
DBMS_AQADM.CREATE_QUEUE
(queue_name => 'Q1',queue_table => 'QT1');
Object Name
Object Type
70793
Q1
QUEUE
juliandyke.com
juliandyke.com
In Oracle 11.1 this statement uses the LOAD TABLE CONVENTIONAL operation
STAT #3 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=1 pr=5 pw=5
time=0 us)')
Object ID
Object Name
Object Type
70581
QT1
TABLE
70586
SYS_C009433
INDEX
70588
AQ$_QT1_1
INDEX
juliandyke.com
juliandyke.com
The statement selects all rows in the queue specified by :1 with a state of :2
The FIRST_ROWS(1) hint is used to optimize the plan
The statement locks any rows to be deleted
This will generate undo/redo
The statement uses the FOR UPDATE SKIP LOCKED clause to skip any rows
still locked by ongoing transactions
juliandyke.com
juliandyke.com
Queues
Exception Queues
Object ID
Object Name
Object Type
Queue Type
70793
Q1
QUEUE
NORMAL
70794
Q1E
QUEUE
EXCEPTION
juliandyke.com
Queues
Exception Queues
juliandyke.com
juliandyke.com
The following objects will be created (object IDs and constraint IDs will vary):
Object ID
Object Name
Object Type
Object ID
Object Name
Object Type
70756
QT1
TABLE
70767
AQ$_QT1_H
TABLE
70757
SYS_LOB0000070581C00032$
$
LOB
70768
SYS_IOT_TOP_70767
INDEX
70758
SYS_IL0000070581C00032$$
LOB INDEX
70769
AQ$_QT1_G
TABLE
70759
SYS_C009457
INDEX
70770
SYS_IOT_OVER_70769
TABLE
70760
AQ$_QT1_S
TABLE
70771
SYS_IOT_TOP_70769
INDEX
70761
SYS_C009460
INDEX
70772
AQ$_QT1_I
TABLE
70762
AQ$_QT1_N
SEQUENCE
70773
SYS_IOT_TOP_70772
INDEX
70763
AQ$QT1_S
VIEW
70774
QT70756_BUFFER
VIEW
70764
AQ$_QT1_V
EVAL CTXT
70775
AQ$QT1
VIEW
70765
AQ$_QT1_T
TABLE
70776
AQ$_QT1_F
VIEW
70766
SYS_IOT_TOP_70765
INDEX
70777
AQ$_QT1_E
QUEUE
juliandyke.com
AQ$_<queue_table_name>_I
IOT that maintains state for dequeue operations
One row per message per recipient/subscriber
AQ$_<queue_table_name>_S
Heap table containing information about subscribers
AQ$_<queue_table_name>_H
IOT used to store dequeue history
One row per message per recipient/subscriber
AQ$_<queue_table_name>_G
IOT correlating messages to subscriber signatures
juliandyke.com
AQ$_<queue_table_name>_T
IOT used queue monitor to manage timed operations
e.g. AQ$_QT3_T
Column
Name
Data Type
NEXT_DATE
TIMESTAMP
TXN_ID
VARCHAR2(30)
MSGID
RAW(16)
ACTION
NUMBER
juliandyke.com
AQ$_<queue_table_name>_I
IOT that maintains state for dequeue operations
Column Name
Data Type
SUBSCRIBER
NUMBER
NAME
VARCHAR2(30)
QUEUE#
NUMBER
MSG_ENQ_TIME
TIMESTAMP
MSG_STEP_NO
NUMBER
MSG_CHAIN_NO
NUMBER
MSG_LOCAL_ORDER_N
O
NUMBER
MSG_ID
RAW(16)
HINT
ROWID
SPARE
RAW(16)
juliandyke.com
AQ$_<queue_table_name>_S
Heap table containing information about subscribers
Column Name
Data Type
SUBSCRIBER_ID
NUMBER
QUEUE_NAME
VARCHAR2(30)
NAME
VARCHAR2(30)
ADDRESS
VARCHAR2(1024)
PROTOCOL
NUMBER
SUBSCRIBER_TYPE
NUMBER
RULE_NAME
VARCHAR2(30)
TRANS_NAME
VARCHAR2(65)
RULESET_NAME
VARCHAR2(65)
NEGATIVE_RULESET_NAME
VARCHAR2(65)
CREATION_TIME
TIMESTAMP(6)
MODIFICATION_TIME
TIMESTAMP(6)
DELETION_TIME
TIMESTAMP(6)
SCN_AT_REMOVE
NUMBER
juliandyke.com
AQ$_<queue_table_name>_H
IOT used to store dequeue history
Column Name
Data Type
MSGID
RAW(16)
SUBSCRIBER#
NUMBER
NAME
VARCHAR2(30)
ADDRESS#
NUMBER
DEQUEUE_TIME
TIMESTAMP
TRANSACTION_ID
VARCHAR2(30)
DEQUEUE_USER
VARCHAR2(30)
PROPAGATED_MSGID
RAW(16)
RETRY_COUNT
NUMBER
HINT
ROWID
SPARE
RAW(16)
juliandyke.com
AQ$_<queue_table_name>_G
IOT correlating messages to subscriber signatures
Column
Name
Data Type
NAME
VARCHAR2(30)
ADDRESS#
NUMBER
SIGN
SYS.AQ$_SIG_PRO
P
DBS_SIGN
SYS.AQ$_SIG_PRO
juliandyke.com
By default six indexes are created for each queue table. For example:
Index Name
Index Type
#
Columns
Table Name
SYS_C009457
NORMAL
QT3
SYS_C009460
NORMAL
AQ$_QT3_S
SYS_IOT_TOP_7076
5
IOT
AQ$_QT3_T
SYS_IOT_TOP_7076
7
IOT
AQ$_QT3_H
AQ$_QT3_
G
SYS_IOT_TOP_7076
IOT
Index9 columns for NORMAL indexes are:
SYS_IOT_TOP_7077
Index Name
2
IOT
Column
#
8
Column Name
SYS_C00945
7
MSGID
SYS_C00946
SUBSCRIBER_ID
AQ$_QT3_I
Index columns
0 for IOT indexes are shown on previous slides
juliandyke.com
juliandyke.com
juliandyke.com
Column Name
Data Type
Column Name
Data Type
QUEUE
VARCHAR2(30)
RETRY_COUNT
NUMBER
MSG_ID
RAW(16)
VARCHAR2(30)
CORR_ID
VARCHAR2(128)
EXCEPTION_QUEUE_OWNE
R
MSG_PRIORITY
NUMBER
EXCEPTION_QUEUE
VARCHAR2(30)
MSG_STATE
VARCHAR2(16)
USER_DATA
TYPE1
DELAY
DATE
PROPAGATED_MSGID
RAW(16)
DELAY_TIMESTAMP
TIMESTAMP(6)
SENDER_NAME
VARCHAR2(30)
EXPIRATION
NUMBER
SENDER_ADDRESS
VARCHAR2(1024)
ENQ_TIME
DATE
SENDER_PROTOCOL
NUMBER
ENQ_TIMESTAMP
TIMESTAMP(6)
ORIGINAL_MSGID
RAW(16)
ENQ_USER_ID
VARCHAR2(30)
ORIGINAL_QUEUE_NAME
VARCHAR2(30)
ENQ_TXN_ID
VARCHAR2(30)
ORIGINAL_QUEUE_OWNER
VARCHAR2(30)
DEQ_TIME
DATE
EXPIRATION_REASON
VARCHAR2(31)
DEQ_TIMESTAMP
TIMESTAMP(6)
CONSUMER_NAME
VARCHAR2(30)
DEQ_USER_ID
VARCHAR2(30)
ADDRESS
VARCHAR2(1024)
DEQ_TXN_ID
VARCHAR2(30)
PROTOCOL
NUMBER
juliandyke.com
juliandyke.com
juliandyke.com
The following code dequeues a message for one of the named recipients
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_deqopt dbms_aq.dequeue_options_t;
l_deq_msgid RAW(16);
BEGIN
l_deqopt.consumer_name := 'CONSUMER2';
dbms_aq.dequeue
(
queue_name => 'Q3',
dequeue_options => l_deqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_deq_msgid
);
END;
Notes
A consumer name MUST be specified
The message must have been enqueued specifically for that consumer
juliandyke.com
The queue monitor (QMNC) process asynchronously checks the timer table
(AQ$_QT3_T) for actions
If any actions are found these are sent to the queue monitor slaves (Q001,
Q002 etc)
When last recipient has dequeued message, queue monitor slaves perform
the following actions
Delete all rows for message in queue history table (AQ$_QT3_H)
Delete row in queue table (QT3) for message
juliandyke.com
Subscribers must exist for the queue before messages can be enqueued
The following code creates two subscribers for queue Q3
DECLARE
l_subscriber sys.aq$_agent;
BEGIN
l_subscriber := sys.aq$_agent ('SUBSCRIBER1',NULL,NULL);
DBMS_AQADM.ADD_SUBSCRIBER
(
queue_name => 'Q3',
subscriber => l_subscriber
);
l_subscriber := sys.aq$_agent ('SUBSCRIBER2',NULL,NULL);
DBMS_AQADM.ADD_SUBSCRIBER
(
queue_name => 'Q3',
subscriber => l_subscriber
);
END;
juliandyke.com
juliandyke.com
juliandyke.com
New subscribers will only be allowed to dequeue messages that have been enqueued after the subscriber was added
juliandyke.com
Array Payloads
Introduction
juliandyke.com
Array Payloads
Enqueue
DECLARE
l_payload TYPE3;
msgprop dbms_aq.message_properties_t;
enqopt dbms_aq.enqueue_options_t;
enq_msgid RAW(16);
BEGIN
l_payload := new TYPE3 (TYPE2 (
TYPE1 (10001,20001,30001),
TYPE1 (10002,20002,30002),
TYPE1 (10003,20003,30003),
TYPE1 (10004,20004,30004)
));
msgprop.expiration := DBMS_AQ.NEVER;
dbms_aq.enqueue
(
queue_name => 'Q4',
enqueue_options => enqopt,
message_properties => msgprop,
payload => l_payload,
msgid => enq_msgid
);
END;
juliandyke.com
Array Payloads
Dequeue
SET SERVEROUTPUT ON
DECLARE
l_payload TYPE3;
msgprop dbms_aq.message_properties_t;
deqopt dbms_aq.dequeue_options_t;
deq_msgid RAW(16);
BEGIN
dbms_aq.dequeue
(
queue_name => 'Q4',
dequeue_options => deqopt,
message_properties => msgprop,
payload => l_payload,
msgid => deq_msgid
);
FOR i IN 1..message.c1.COUNT
LOOP
DBMS_OUTPUT.PUT ('C1 = '||TO_CHAR (l_payload.c1(i).c1)||' ');
DBMS_OUTPUT.PUT ('C2 = '||TO_CHAR (l_payload.c1(i).c2)||' ');
DBMS_OUTPUT.PUT ('C3 = '||TO_CHAR (l_payload.c1(i).c3));
DBMS_OUTPUT.NEW_LINE ();
END LOOP;
END;
juliandyke.com
Buffered Messages
Introduction
juliandyke.com
Buffered Messages
Introduction
The following definitions are used with the examples in this section
BEGIN
dbms_aqadm.create_queue_table ('QT1','TYPE1')
dbms_aqadm.create_queue ('Q1','QT1');
dbms_aqadm.start_queue ('Q1');
END;
juliandyke.com
Buffered Messages
Enqueue
juliandyke.com
Buffered Messages
Dequeue
juliandyke.com
Buffered Messages
Memory Usage
After
Befor
e
After
10,324,448
recov_kgqmsub
336
504
kwqbsinfy:mpr
480
2,448,480
kwqbsinfy:cco
332
332
image handles
84
428,512
kwqbsinfy:sta
208
312
kwqbsinfy:bms
72
387,692
spilled:kwqbl
216
288
kggmem_fl_1
44
224,444
256
256
2,072
88,060
kgqmsub
144
216
Sender info
14,140
19,796
deqtree_kgqmctx
136
192
recov_kgqbtctx
12,288
16,384
substree_kgqmctx
120
160
kwqbcqini:spilledovermsgs
2,952
3,936
120
160
kwqbsinfy:bqg
1,236
1,648
msgtree_kgqmctx
120
160
924
1,232
name_kgqmsub
32
48
kodpaih3
kggbt_alloc_block
recov_kggmctx
juliandyke.com
Buffered Messages
Database Objects
Additional database objects are created the first time a buffered message is
enqueued on a queue table
This will cause elapsed time of first enqueue operation to be high
Object ID
Object Name
Object Type
72638
AQ$_QT3_P
TABLE
72639
SYS_LOB0000072638C00032$
$
LOB
72640
SYS_IL0000072638C00032$$
LOB
INDEX
72641
SYS_C0010003
INDEX
juliandyke.com
Buffered Messages
Database Objects
Data Type
Column Name
Data Type
Q_NAME
VARCHAR2(30)
DEQ_TIME
DATE
MSGID
RAW(16)
DEQ_UID
VARCHAR2(30)
CORRID
VARCHAR2(128)
DEQ_TID
VARCHAR2(30)
PRIORITY
NUMBER
RETRY_COUNT
NUMBER
STATE
VARCHAR2(16)
VARCHAR2(30)
DELAY
DATE
EXCEPTION_QSCHEM
A
EXPIRATION
NUMBER
EXCEPTION_QUEUE
VARCHAR2(30)
TIME_MANAGER_INF
O
TIMESTAMP(6)
STEP_NO
NUMBER
RECIPIENT_KEY
NUMBER
LOCAL_ORDER_NO
NUMBER
DEQUEUE_MSGID
RAW(16)
CHAIN_NO
NUMBER
SENDER_NAME
VARCHAR2(30)
CSCN
NUMBER
SENDER_ADDRESS
VARCHAR2(1024)
DSCN
NUMBER
SENDER_PROTOCOL
NUMBER
ENQ_TIME
DATE
USER_DATA
TYPE1
ENQ_UID
VARCHAR2(30)
USER_PROP
SYS.ANYDATA
ENQ_TID
VARCHAR2(30)
juliandyke.com
Buffered Messages
Database Objects
Two view definitions are also updated when the first buffered message is
enqueued:
AQ$<queue_table_name>
e.g. AQ$QT3
reports all messages in persistent and buffered queues
AQ$_<queue_table_name>_F
e.g. AQ$_QT3_F
reports all messages that have not yet been dequeued in both
persistent and buffered queues
juliandyke.com
Buffered Messages
Database Objects
juliandyke.com
Buffered Messages
Database Objects
Data Type
OID
NUMBER
MSGNUM
NUMBER
MSGID
RAW(16)
SUB
NUMBER
SEQNUM
NUMBER
RSUBS
SYS.AQ$_RECIPIENT
The RSUBS column is stored asS a LOB
juliandyke.com
Buffered Messages
Spillage
Limited to
5000 buffered messages
15000 captured messages
juliandyke.com
Buffered Messages
Database Objects
For a multiple consumer queue the following objects will be created when the
first buffered message is enqueued:
Object ID
Object Name
Object Type
72638
AQ$_QT3_P
TABLE
72639
SYS_LOB0000072638C00032$$
LOB
72640
SYS_IL0000072638C00032$$
LOB
INDEX
72641
SYS_C0010003
INDEX
72642
AQ$_QT3_D
TABLE
72643
SYS_IOT_OVER_72642
TABLE
72644
SYS_LOB0000072642C00006$$
LOB
72645
SYS_IL0000072642C00006$$
INDEX
72646
SYS_IOT_TOP_72642
INDEX
juliandyke.com
Performance
Elapsed Times
Enqueue
No Commit
Dequeue
Commit
No Commit
Commit
Single Consumer
PERSISTENT
ON COMMIT
4.77
10.99
5.75
9.62
Single Consumer
PERSISTENT
IMMEDIATE
10.80
11.41
8.77
9.78
Single Consumer
BUFFERED
IMMEDIATE
2.32
2.60
1.53
2.13
Single Consumer
PERSISTENT
ON COMMIT
VARRAY(10) OF TYPE1
0.66
1.38
1.00
1.35
Multi Consumer
PERSISTENT
ON COMMIT
2 recipients
6.40
14.45
6.36
11.20
Multi Consumer
PERSISTENT
ON COMMIT
2 subscribers
6.02
14.59
6.54
11.40
10000 TYPE1 messages enqueued then 10000 messages dequeued. Average of 5 runs. Oracle 10.2 on RHEL4.5
x86
juliandyke.com
Performance
Redo Generation
Enqueue
No Commit
Dequeue
Commit
No Commit
Commit
Single Consumer
PERSISTENT
ON COMMIT
9223
15491
10806
15521
Single Consumer
PERSISTENT
IMMEDIATE
15165
15485
14936
14904
Single Consumer
BUFFERED
IMMEDIATE
1211
1831
1381
1832
Multi Consumer
PERSISTENT
ON COMMIT
2 recipients
16459
23324
8102
12521
Multi Consumer
PERSISTENT
ON COMMIT
2 subscribers
15832
23404
7934
12953
Single Consumer
PERSISTENT
ON COMMIT
VARRAY(10) OF TYPE1
10 TYPE1 messages enqueued then 10 messages dequeued. Average of 5 runs. Oracle 10.2 on RHEL4.5 x86
juliandyke.com
Conclusion
juliandyke.com
juliandyke.com