]> granicus.if.org Git - postgresql/blob - src/include/pgstat.h
Remove the pgstat_drop_relation() call from smgr_internal_unlink(), because
[postgresql] / src / include / pgstat.h
1 /* ----------
2  *      pgstat.h
3  *
4  *      Definitions for the PostgreSQL statistics collector daemon.
5  *
6  *      Copyright (c) 2001-2007, PostgreSQL Global Development Group
7  *
8  *      $PostgreSQL: pgsql/src/include/pgstat.h,v 1.64 2007/07/08 22:23:16 tgl Exp $
9  * ----------
10  */
11 #ifndef PGSTAT_H
12 #define PGSTAT_H
13
14 #include "libpq/pqcomm.h"
15 #include "utils/hsearch.h"
16 #include "utils/rel.h"
17 #include "utils/timestamp.h"
18
19
20 /* ----------
21  * The types of backend -> collector messages
22  * ----------
23  */
24 typedef enum StatMsgType
25 {
26         PGSTAT_MTYPE_DUMMY,
27         PGSTAT_MTYPE_TABSTAT,
28         PGSTAT_MTYPE_TABPURGE,
29         PGSTAT_MTYPE_DROPDB,
30         PGSTAT_MTYPE_RESETCOUNTER,
31         PGSTAT_MTYPE_AUTOVAC_START,
32         PGSTAT_MTYPE_VACUUM,
33         PGSTAT_MTYPE_ANALYZE,
34         PGSTAT_MTYPE_BGWRITER
35 } StatMsgType;
36
37 /* ----------
38  * The data type used for counters.
39  * ----------
40  */
41 typedef int64 PgStat_Counter;
42
43 /* ----------
44  * PgStat_TableCounts                   The actual per-table counts kept by a backend
45  *
46  * This struct should contain only actual event counters, because we memcmp
47  * it against zeroes to detect whether there are any counts to transmit.
48  * It is a component of PgStat_TableStatus (within-backend state) and
49  * PgStat_TableEntry (the transmitted message format).
50  *
51  * Note: for a table, tuples_returned is the number of tuples successfully
52  * fetched by heap_getnext, while tuples_fetched is the number of tuples
53  * successfully fetched by heap_fetch under the control of bitmap indexscans.
54  * For an index, tuples_returned is the number of index entries returned by
55  * the index AM, while tuples_fetched is the number of tuples successfully
56  * fetched by heap_fetch under the control of simple indexscans for this index.
57  *
58  * tuples_inserted/tuples_updated/tuples_deleted count attempted actions,
59  * regardless of whether the transaction committed.  new_live_tuples and
60  * new_dead_tuples are properly adjusted depending on commit or abort.
61  * Note that new_live_tuples can be negative!
62  * ----------
63  */
64 typedef struct PgStat_TableCounts
65 {
66         PgStat_Counter t_numscans;
67
68         PgStat_Counter t_tuples_returned;
69         PgStat_Counter t_tuples_fetched;
70
71         PgStat_Counter t_tuples_inserted;
72         PgStat_Counter t_tuples_updated;
73         PgStat_Counter t_tuples_deleted;
74
75         PgStat_Counter t_new_live_tuples;
76         PgStat_Counter t_new_dead_tuples;
77
78         PgStat_Counter t_blocks_fetched;
79         PgStat_Counter t_blocks_hit;
80 } PgStat_TableCounts;
81
82
83 /* ------------------------------------------------------------
84  * Structures kept in backend local memory while accumulating counts
85  * ------------------------------------------------------------
86  */
87
88
89 /* ----------
90  * PgStat_TableStatus                   Per-table status within a backend
91  *
92  * Most of the event counters are nontransactional, ie, we count events
93  * in committed and aborted transactions alike.  For these, we just count
94  * directly in the PgStat_TableStatus.  However, new_live_tuples and
95  * new_dead_tuples must be derived from tuple insertion and deletion counts
96  * with awareness of whether the transaction or subtransaction committed or
97  * aborted.  Hence, we also keep a stack of per-(sub)transaction status
98  * records for every table modified in the current transaction.  At commit
99  * or abort, we propagate tuples_inserted and tuples_deleted up to the
100  * parent subtransaction level, or out to the parent PgStat_TableStatus,
101  * as appropriate.
102  * ----------
103  */
104 typedef struct PgStat_TableStatus
105 {
106         Oid                     t_id;                           /* table's OID */
107         bool            t_shared;                       /* is it a shared catalog? */
108         struct PgStat_TableXactStatus *trans;   /* lowest subxact's counts */
109         PgStat_TableCounts t_counts;    /* event counts to be sent */
110 } PgStat_TableStatus;
111
112 /* ----------
113  * PgStat_TableXactStatus               Per-table, per-subtransaction status
114  * ----------
115  */
116 typedef struct PgStat_TableXactStatus
117 {
118         PgStat_Counter tuples_inserted; /* tuples inserted in (sub)xact */
119         PgStat_Counter tuples_deleted;  /* tuples deleted in (sub)xact */
120         int                     nest_level;                     /* subtransaction nest level */
121         /* links to other structs for same relation: */
122         struct PgStat_TableXactStatus *upper;   /* next higher subxact if any */
123         PgStat_TableStatus *parent;                             /* per-table status */
124         /* structs of same subxact level are linked here: */
125         struct PgStat_TableXactStatus *next;    /* next of same subxact */
126 } PgStat_TableXactStatus;
127
128
129 /* ------------------------------------------------------------
130  * Message formats follow
131  * ------------------------------------------------------------
132  */
133
134
135 /* ----------
136  * PgStat_MsgHdr                                The common message header
137  * ----------
138  */
139 typedef struct PgStat_MsgHdr
140 {
141         StatMsgType m_type;
142         int                     m_size;
143 } PgStat_MsgHdr;
144
145 /* ----------
146  * Space available in a message.  This will keep the UDP packets below 1K,
147  * which should fit unfragmented into the MTU of the lo interface on most
148  * platforms. Does anybody care for platforms where it doesn't?
149  * ----------
150  */
151 #define PGSTAT_MSG_PAYLOAD      (1000 - sizeof(PgStat_MsgHdr))
152
153
154 /* ----------
155  * PgStat_MsgDummy                              A dummy message, ignored by the collector
156  * ----------
157  */
158 typedef struct PgStat_MsgDummy
159 {
160         PgStat_MsgHdr m_hdr;
161 } PgStat_MsgDummy;
162
163
164 /* ----------
165  * PgStat_TableEntry                    Per-table info in a MsgTabstat
166  * ----------
167  */
168 typedef struct PgStat_TableEntry
169 {
170         Oid                     t_id;
171         PgStat_TableCounts t_counts;
172 } PgStat_TableEntry;
173
174 /* ----------
175  * PgStat_MsgTabstat                    Sent by the backend to report table
176  *                                                              and buffer access statistics.
177  * ----------
178  */
179 #define PGSTAT_NUM_TABENTRIES  \
180         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int))  \
181          / sizeof(PgStat_TableEntry))
182
183 typedef struct PgStat_MsgTabstat
184 {
185         PgStat_MsgHdr m_hdr;
186         Oid                     m_databaseid;
187         int                     m_nentries;
188         int                     m_xact_commit;
189         int                     m_xact_rollback;
190         PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
191 } PgStat_MsgTabstat;
192
193
194 /* ----------
195  * PgStat_MsgTabpurge                   Sent by the backend to tell the collector
196  *                                                              about dead tables.
197  * ----------
198  */
199 #define PGSTAT_NUM_TABPURGE  \
200         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int))  \
201          / sizeof(Oid))
202
203 typedef struct PgStat_MsgTabpurge
204 {
205         PgStat_MsgHdr m_hdr;
206         Oid                     m_databaseid;
207         int                     m_nentries;
208         Oid                     m_tableid[PGSTAT_NUM_TABPURGE];
209 } PgStat_MsgTabpurge;
210
211
212 /* ----------
213  * PgStat_MsgDropdb                             Sent by the backend to tell the collector
214  *                                                              about a dropped database
215  * ----------
216  */
217 typedef struct PgStat_MsgDropdb
218 {
219         PgStat_MsgHdr m_hdr;
220         Oid                     m_databaseid;
221 } PgStat_MsgDropdb;
222
223
224 /* ----------
225  * PgStat_MsgResetcounter               Sent by the backend to tell the collector
226  *                                                              to reset counters
227  * ----------
228  */
229 typedef struct PgStat_MsgResetcounter
230 {
231         PgStat_MsgHdr m_hdr;
232         Oid                     m_databaseid;
233 } PgStat_MsgResetcounter;
234
235
236 /* ----------
237  * PgStat_MsgAutovacStart               Sent by the autovacuum daemon to signal
238  *                                                              that a database is going to be processed
239  * ----------
240  */
241 typedef struct PgStat_MsgAutovacStart
242 {
243         PgStat_MsgHdr m_hdr;
244         Oid                     m_databaseid;
245         TimestampTz m_start_time;
246 } PgStat_MsgAutovacStart;
247
248
249 /* ----------
250  * PgStat_MsgVacuum                             Sent by the backend or autovacuum daemon
251  *                                                              after VACUUM or VACUUM ANALYZE
252  * ----------
253  */
254 typedef struct PgStat_MsgVacuum
255 {
256         PgStat_MsgHdr m_hdr;
257         Oid                     m_databaseid;
258         Oid                     m_tableoid;
259         bool            m_analyze;
260         bool            m_autovacuum;
261         TimestampTz m_vacuumtime;
262         PgStat_Counter m_tuples;
263 } PgStat_MsgVacuum;
264
265
266 /* ----------
267  * PgStat_MsgAnalyze                    Sent by the backend or autovacuum daemon
268  *                                                              after ANALYZE
269  * ----------
270  */
271 typedef struct PgStat_MsgAnalyze
272 {
273         PgStat_MsgHdr m_hdr;
274         Oid                     m_databaseid;
275         Oid                     m_tableoid;
276         bool            m_autovacuum;
277         TimestampTz m_analyzetime;
278         PgStat_Counter m_live_tuples;
279         PgStat_Counter m_dead_tuples;
280 } PgStat_MsgAnalyze;
281
282
283 /* ----------
284  * PgStat_MsgBgWriter           Sent by the bgwriter to update statistics.
285  * ----------
286  */
287 typedef struct PgStat_MsgBgWriter
288 {
289         PgStat_MsgHdr m_hdr;
290
291         PgStat_Counter  m_timed_checkpoints;
292         PgStat_Counter  m_requested_checkpoints;
293         PgStat_Counter  m_buf_written_checkpoints;
294         PgStat_Counter  m_buf_written_clean;
295         PgStat_Counter  m_maxwritten_clean;
296 } PgStat_MsgBgWriter;
297
298
299 /* ----------
300  * PgStat_Msg                                   Union over all possible messages.
301  * ----------
302  */
303 typedef union PgStat_Msg
304 {
305         PgStat_MsgHdr msg_hdr;
306         PgStat_MsgDummy msg_dummy;
307         PgStat_MsgTabstat msg_tabstat;
308         PgStat_MsgTabpurge msg_tabpurge;
309         PgStat_MsgDropdb msg_dropdb;
310         PgStat_MsgResetcounter msg_resetcounter;
311         PgStat_MsgAutovacStart msg_autovacuum;
312         PgStat_MsgVacuum msg_vacuum;
313         PgStat_MsgAnalyze msg_analyze;
314         PgStat_MsgBgWriter msg_bgwriter;
315 } PgStat_Msg;
316
317
318 /* ------------------------------------------------------------
319  * Statistic collector data structures follow
320  *
321  * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
322  * data structures change.
323  * ------------------------------------------------------------
324  */
325
326 #define PGSTAT_FILE_FORMAT_ID   0x01A5BC96
327
328 /* ----------
329  * PgStat_StatDBEntry                   The collector's data per database
330  * ----------
331  */
332 typedef struct PgStat_StatDBEntry
333 {
334         Oid                     databaseid;
335         PgStat_Counter n_xact_commit;
336         PgStat_Counter n_xact_rollback;
337         PgStat_Counter n_blocks_fetched;
338         PgStat_Counter n_blocks_hit;
339         PgStat_Counter n_tuples_returned;
340         PgStat_Counter n_tuples_fetched;
341         PgStat_Counter n_tuples_inserted;
342         PgStat_Counter n_tuples_updated;
343         PgStat_Counter n_tuples_deleted;
344         TimestampTz last_autovac_time;
345
346         /*
347          * tables must be last in the struct, because we don't write the pointer
348          * out to the stats file.
349          */
350         HTAB       *tables;
351 } PgStat_StatDBEntry;
352
353
354 /* ----------
355  * PgStat_StatTabEntry                  The collector's data per table (or index)
356  * ----------
357  */
358 typedef struct PgStat_StatTabEntry
359 {
360         Oid                     tableid;
361
362         PgStat_Counter numscans;
363
364         PgStat_Counter tuples_returned;
365         PgStat_Counter tuples_fetched;
366
367         PgStat_Counter tuples_inserted;
368         PgStat_Counter tuples_updated;
369         PgStat_Counter tuples_deleted;
370
371         PgStat_Counter n_live_tuples;
372         PgStat_Counter n_dead_tuples;
373         PgStat_Counter last_anl_tuples;
374
375         PgStat_Counter blocks_fetched;
376         PgStat_Counter blocks_hit;
377
378         TimestampTz vacuum_timestamp;           /* user initiated vacuum */
379         TimestampTz autovac_vacuum_timestamp;           /* autovacuum initiated */
380         TimestampTz analyze_timestamp;          /* user initiated */
381         TimestampTz autovac_analyze_timestamp;          /* autovacuum initiated */
382 } PgStat_StatTabEntry;
383
384
385 /*
386  * Global statistics kept in the stats collector
387  */
388 typedef struct PgStat_GlobalStats
389 {
390         PgStat_Counter  timed_checkpoints;
391         PgStat_Counter  requested_checkpoints;
392         PgStat_Counter  buf_written_checkpoints;
393         PgStat_Counter  buf_written_clean;
394         PgStat_Counter  maxwritten_clean;
395 } PgStat_GlobalStats;
396
397
398 /* ----------
399  * Shared-memory data structures
400  * ----------
401  */
402
403 /* Max length of st_activity string ... perhaps replace with a GUC var? */
404 #define PGBE_ACTIVITY_SIZE      1024
405
406 /* ----------
407  * PgBackendStatus
408  *
409  * Each live backend maintains a PgBackendStatus struct in shared memory
410  * showing its current activity.  (The structs are allocated according to
411  * BackendId, but that is not critical.)  Note that the collector process
412  * has no involvement in, or even access to, these structs.
413  * ----------
414  */
415 typedef struct PgBackendStatus
416 {
417         /*
418          * To avoid locking overhead, we use the following protocol: a backend
419          * increments st_changecount before modifying its entry, and again after
420          * finishing a modification.  A would-be reader should note the value of
421          * st_changecount, copy the entry into private memory, then check
422          * st_changecount again.  If the value hasn't changed, and if it's even,
423          * the copy is valid; otherwise start over.  This makes updates cheap
424          * while reads are potentially expensive, but that's the tradeoff we want.
425          */
426         int                     st_changecount;
427
428         /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
429         int                     st_procpid;
430
431         /* Times when current backend, transaction, and activity started */
432         TimestampTz st_proc_start_timestamp;
433         TimestampTz st_txn_start_timestamp;
434         TimestampTz st_activity_start_timestamp;
435
436         /* Database OID, owning user's OID, connection client address */
437         Oid                     st_databaseid;
438         Oid                     st_userid;
439         SockAddr        st_clientaddr;
440
441         /* Is backend currently waiting on an lmgr lock? */
442         bool            st_waiting;
443
444         /* current command string; MUST be null-terminated */
445         char            st_activity[PGBE_ACTIVITY_SIZE];
446 } PgBackendStatus;
447
448
449 /* ----------
450  * GUC parameters
451  * ----------
452  */
453 extern bool pgstat_collect_startcollector;
454 extern bool pgstat_collect_resetonpmstart;
455 extern bool pgstat_collect_tuplelevel;
456 extern bool pgstat_collect_blocklevel;
457 extern bool pgstat_collect_querystring;
458
459 /*
460  * BgWriter statistics counters are updated directly by bgwriter and bufmgr
461  */
462 extern PgStat_MsgBgWriter BgWriterStats;
463
464 /* ----------
465  * Functions called from postmaster
466  * ----------
467  */
468 extern Size BackendStatusShmemSize(void);
469 extern void CreateSharedBackendStatus(void);
470
471 extern void pgstat_init(void);
472 extern int      pgstat_start(void);
473 extern void pgstat_reset_all(void);
474 extern void allow_immediate_pgstat_restart(void);
475 #ifdef EXEC_BACKEND
476 extern void PgstatCollectorMain(int argc, char *argv[]);
477 #endif
478
479
480 /* ----------
481  * Functions called from backends
482  * ----------
483  */
484 extern void pgstat_ping(void);
485
486 extern void pgstat_report_tabstat(bool force);
487 extern void pgstat_vacuum_tabstat(void);
488 extern void pgstat_drop_database(Oid databaseid);
489
490 extern void pgstat_clear_snapshot(void);
491 extern void pgstat_reset_counters(void);
492
493 extern void pgstat_report_autovac(Oid dboid);
494 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
495                                          bool analyze, PgStat_Counter tuples);
496 extern void pgstat_report_analyze(Oid tableoid, bool shared,
497                                           PgStat_Counter livetuples,
498                                           PgStat_Counter deadtuples);
499
500 extern void pgstat_initialize(void);
501 extern void pgstat_bestart(void);
502
503 extern void pgstat_report_activity(const char *what);
504 extern void pgstat_report_txn_timestamp(TimestampTz tstamp);
505 extern void pgstat_report_waiting(bool waiting);
506
507 extern void pgstat_initstats(Relation rel);
508
509 /* nontransactional event counts are simple enough to inline */
510
511 #define pgstat_count_heap_scan(rel)                                                                             \
512         do {                                                                                                                            \
513                 if (pgstat_collect_tuplelevel && (rel)->pgstat_info != NULL)    \
514                         (rel)->pgstat_info->t_counts.t_numscans++;                                      \
515         } while (0)
516 #define pgstat_count_heap_getnext(rel)                                                                  \
517         do {                                                                                                                            \
518                 if (pgstat_collect_tuplelevel && (rel)->pgstat_info != NULL)    \
519                         (rel)->pgstat_info->t_counts.t_tuples_returned++;                       \
520         } while (0)
521 #define pgstat_count_heap_fetch(rel)                                                                    \
522         do {                                                                                                                            \
523                 if (pgstat_collect_tuplelevel && (rel)->pgstat_info != NULL)    \
524                         (rel)->pgstat_info->t_counts.t_tuples_fetched++;                        \
525         } while (0)
526 #define pgstat_count_index_scan(rel)                                                                    \
527         do {                                                                                                                            \
528                 if (pgstat_collect_tuplelevel && (rel)->pgstat_info != NULL)    \
529                         (rel)->pgstat_info->t_counts.t_numscans++;                                      \
530         } while (0)
531 #define pgstat_count_index_tuples(rel, n)                                                               \
532         do {                                                                                                                            \
533                 if (pgstat_collect_tuplelevel && (rel)->pgstat_info != NULL)    \
534                         (rel)->pgstat_info->t_counts.t_tuples_returned += (n);          \
535         } while (0)
536 #define pgstat_count_buffer_read(rel)                                                                   \
537         do {                                                                                                                            \
538                 if (pgstat_collect_blocklevel && (rel)->pgstat_info != NULL)    \
539                         (rel)->pgstat_info->t_counts.t_blocks_fetched++;                        \
540         } while (0)
541 #define pgstat_count_buffer_hit(rel)                                                                    \
542         do {                                                                                                                            \
543                 if (pgstat_collect_blocklevel && (rel)->pgstat_info != NULL)    \
544                         (rel)->pgstat_info->t_counts.t_blocks_hit++;                            \
545         } while (0)
546
547 extern void pgstat_count_heap_insert(Relation rel);
548 extern void pgstat_count_heap_update(Relation rel);
549 extern void pgstat_count_heap_delete(Relation rel);
550
551 extern void AtEOXact_PgStat(bool isCommit);
552 extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth);
553
554 extern void AtPrepare_PgStat(void);
555 extern void PostPrepare_PgStat(void);
556
557 extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info,
558                                                                            void *recdata, uint32 len);
559 extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
560                                                                           void *recdata, uint32 len);
561
562 extern void pgstat_send_bgwriter(void);
563
564 /* ----------
565  * Support functions for the SQL-callable functions to
566  * generate the pgstat* views.
567  * ----------
568  */
569 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
570 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
571 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
572 extern int      pgstat_fetch_stat_numbackends(void);
573 extern PgStat_GlobalStats *pgstat_fetch_global(void);
574
575 #endif   /* PGSTAT_H */