Compare commits

...

7 Commits
main ... 2.0.1

Author SHA1 Message Date
Hamid Akhtar 02d459af4e Updating release notes for the 2.0.1 release. 2023-05-25 19:42:57 +05:00
EvgeniyPatlan 2b91bda2dd
Merge pull request #398 from EvgeniyPatlan/REL_2_STABLE
ENG-7 Update pg-stat-monitor.spec
2023-05-17 15:40:52 +02:00
EvgeniyPatlan f0fd3418c3
ENG-7 Update pg-stat-monitor.spec 2023-05-17 16:38:43 +03:00
Hamid Akhtar c608a9cf71 Version bumped for the 2.0.1 release. 2023-05-17 13:10:51 +05:00
Hamid Akhtar 9aed81e942
PG-624: pg_stat_monitor: Possible server crash when running pgbench with pg_stat_monitor loaded (#396)
PG-624: pg_stat_monitor: Possible server crash when running pgbench
with pg_stat_monitor loaded

It appears that this issue was being caused by improper handling of
dynamic number of buckets. This commit resolves the issue.

Also, as part of a larger cleanup, memory context has been moved to
local space from shared storage. Also, some unwanted
and no-longer-needed variables are removed.

Co-authored-by: Muhammad Usama <muhammad.usama@percona.com>
2023-05-12 21:51:55 +05:00
Mikail 8687edf28d Make pg_config configurable in Makefile invocation (#392)
This allows to override the `PG_CONFIG` variable through environment variables
when wanting to use another one that is not in the `PATH`.
2023-05-10 14:25:15 +05:00
Hamid Akhtar 3844d7b908 PG-613: Postgresql crashes with Segmentation fault when query plan is enabled on large queries
The return value for snprintf was incorrectly being recorded as plan
length. That's been resolved.

As part of this fix, we've also elminated the possibility of a potential
memory leak when plan text was being saved.

Co-authored-by: Hamid Akhtar <hamid.akhtar@percona.com>
Co-authored-by: Muhammad Usama <muhammad.usama@percona.com>
2023-04-19 16:30:17 +05:00
8 changed files with 62 additions and 31 deletions

View File

@ -2,7 +2,7 @@
"name": "pg_stat_monitor",
"abstract": "PostgreSQL Query Performance Monitoring Tool",
"description": "pg_stat_monitor is a PostgreSQL Query Performance Monitoring tool, based on PostgreSQL's contrib module pg_stat_statements. PostgreSQLs pg_stat_statements provides the basic statistics, which is sometimes not enough. The major shortcoming in pg_stat_statements is that it accumulates all the queries and their statistics and does not provide aggregated statistics nor histogram information. In this case, a user would need to calculate the aggregates, which is quite an expensive operation.",
"version": "2.0.0",
"version": "2.0.1",
"maintainer": [
"ibrar.ahmed@percona.com"
],
@ -10,9 +10,9 @@
"provides": {
"pg_stat_monitor": {
"abstract": "PostgreSQL Query Performance Monitoring Tool",
"file": "pg_stat_monitor--1.0.sql",
"file": "pg_stat_monitor--2.0.sql",
"docfile": "README.md",
"version": "2.0.0"
"version": "2.0.1"
}
},
"prereqs": {

View File

@ -18,7 +18,7 @@ REGRESS = basic version guc pgsm_query_id functions counters relations database
# which typical installcheck users do not have (e.g. buildfarm clients).
# NO_INSTALLCHECK = 1
PG_CONFIG = pg_config
PG_CONFIG ?= pg_config
ifdef USE_PGXS
MAJORVERSION := $(shell pg_config --version | awk {'print $$2'} | cut -f1 -d".")

View File

@ -2,6 +2,15 @@
Below is the complete list of release notes for every version of ``pg_stat_monitor``.
## 2.0.1
### Bug Fixes
[PG-613](https://jira.percona.com/browse/PG-613) - Fixed the issue with segmentation fault error when the query plan is enabled on large queries.
[PG-624](https://jira.percona.com/browse/PG-624) - Fixed the server crash when running pgbench with pg_stat_monitor loaded by improving the handling of the dynamic number of buckets.
## 2.0.0
### Improvements

View File

@ -23,6 +23,9 @@ static PGSM_HASH_TABLE_HANDLE pgsm_create_bucket_hash(pgsmSharedState * pgsm, ds
static Size pgsm_get_shared_area_size(void);
static void InitializeSharedState(pgsmSharedState * pgsm);
#define PGSM_BUCKET_INFO_SIZE (sizeof(TimestampTz) * pgsm_max_buckets)
#define PGSM_SHARED_STATE_SIZE (sizeof(pgsmSharedState) + PGSM_BUCKET_INFO_SIZE)
#if USE_DYNAMIC_HASH
/* parameter for the shared hash */
static dshash_parameters dsh_params = {
@ -56,7 +59,7 @@ pgsm_query_area_size(void)
Size
pgsm_ShmemSize(void)
{
Size sz = MAXALIGN(sizeof(pgsmSharedState));
Size sz = MAXALIGN(PGSM_SHARED_STATE_SIZE);
sz = add_size(sz, MAX_QUERY_BUF);
#if USE_DYNAMIC_HASH
@ -114,7 +117,7 @@ pgsm_startup(void)
SpinLockInit(&pgsm->mutex);
InitializeSharedState(pgsm);
/* the allocation of pgsmSharedState itself */
p += MAXALIGN(sizeof(pgsmSharedState));
p += MAXALIGN(PGSM_SHARED_STATE_SIZE);
pgsm->raw_dsa_area = p;
dsa = dsa_create_in_place(pgsm->raw_dsa_area,
pgsm_query_area_size(),
@ -138,6 +141,10 @@ pgsm_startup(void)
* references.
*/
dsa_detach(dsa);
pgsmStateLocal.pgsm_mem_cxt = AllocSetContextCreate(TopMemoryContext,
"pg_stat_monitor local store",
ALLOCSET_DEFAULT_SIZES);
}
#ifdef BENCHMARK
@ -158,10 +165,6 @@ InitializeSharedState(pgsmSharedState * pgsm)
{
pg_atomic_init_u64(&pgsm->current_wbucket, 0);
pg_atomic_init_u64(&pgsm->prev_bucket_sec, 0);
memset(&pgsm->bucket_entry, 0, MAX_BUCKETS * sizeof(uint64));
pgsm->pgsm_mem_cxt = AllocSetContextCreate(TopMemoryContext,
"pg_stat_monitor local store",
ALLOCSET_DEFAULT_SIZES);
}
@ -235,6 +238,11 @@ pgsm_attach_shmem(void)
MemoryContextSwitchTo(oldcontext);
}
MemoryContext GetPgsmMemoryContext(void)
{
return pgsmStateLocal.pgsm_mem_cxt;
}
dsa_area *
get_dsa_area_for_query_text(void)
{
@ -290,7 +298,6 @@ hash_entry_alloc(pgsmSharedState * pgsm, pgsmHashKey * key, int encoding)
elog(DEBUG1, "[pg_stat_monitor] hash_entry_alloc: OUT OF MEMORY.");
else if (!found)
{
pgsm->bucket_entry[pg_atomic_read_u64(&pgsm->current_wbucket)]++;
/* New entry, initialize it */
/* reset the statistics */
memset(&entry->counters, 0, sizeof(Counters));

View File

@ -36,7 +36,7 @@ typedef enum pgsmVersion
PG_MODULE_MAGIC;
#define BUILD_VERSION "2.0.0"
#define BUILD_VERSION "2.0.1"
/* Number of output arguments (columns) for various API versions */
#define PG_STAT_MONITOR_COLS_V1_0 52
@ -692,9 +692,30 @@ pgsm_ExecutorEnd(QueryDesc *queryDesc)
/* Extract the plan information in case of SELECT statement */
if (queryDesc->operation == CMD_SELECT && pgsm_enable_query_plan)
{
plan_info.plan_len = snprintf(plan_info.plan_text, PLAN_TEXT_LEN, "%s", pgsm_explain(queryDesc));
plan_info.planid = pgsm_hash_string(plan_info.plan_text, plan_info.plan_len);
plan_ptr = &plan_info;
int rv;
MemoryContext oldctx;
/*
* Making sure it is a per query context so that there's no memory
* leak when executor ends.
*/
oldctx = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt);
rv = snprintf(plan_info.plan_text, PLAN_TEXT_LEN, "%s", pgsm_explain(queryDesc));
/*
* If snprint didn't write anything or there was an error, let's keep
* planinfo as NULL.
*/
if (rv > 0)
{
plan_info.plan_len = (rv < PLAN_TEXT_LEN) ? rv : PLAN_TEXT_LEN - 1;
plan_info.planid = pgsm_hash_string(plan_info.plan_text, plan_info.plan_len);
plan_ptr = &plan_info;
}
/* Switch back to old context */
MemoryContextSwitchTo(oldctx);
}
if (queryId != UINT64CONST(0) && queryDesc->totaltime && pgsm_enabled(exec_nested_level))
@ -1569,7 +1590,7 @@ static void
pgsm_add_to_list(pgsmEntry * entry, char *query_text, int query_len)
{
/* Switch to pgsm memory context */
MemoryContext oldctx = MemoryContextSwitchTo(pgsm_get_ss()->pgsm_mem_cxt);
MemoryContext oldctx = MemoryContextSwitchTo(GetPgsmMemoryContext());
entry->query_text.query_pointer = pnstrdup(query_text, query_len);
lentries = lappend(lentries, entry);
@ -1624,7 +1645,8 @@ static void
pgsm_cleanup_callback(void *arg)
{
/* Reset the memory context holding the list */
MemoryContextReset(pgsm_get_ss()->pgsm_mem_cxt);
MemoryContextReset(GetPgsmMemoryContext());
lentries = NIL;
callback_setup = false;
}
@ -1645,7 +1667,7 @@ pgsm_create_hash_entry(uint64 bucket_id, uint64 queryid, PlanInfo * plan_info)
char *username = NULL;
/* Create an entry in the pgsm memory context */
oldctx = MemoryContextSwitchTo(pgsm_get_ss()->pgsm_mem_cxt);
oldctx = MemoryContextSwitchTo(GetPgsmMemoryContext());
entry = palloc0(sizeof(pgsmEntry));
/*

View File

@ -77,7 +77,6 @@
#define HISTOGRAM_MAX_TIME 50000000
#define MAX_RESPONSE_BUCKET 50
#define INVALID_BUCKET_ID -1
#define MAX_BUCKETS 10
#define TEXT_LEN 255
#define ERROR_MESSAGE_LEN 100
#define REL_TYPENAME_LEN 64
@ -388,8 +387,6 @@ typedef struct pgsmSharedState
slock_t mutex; /* protects following fields only: */
pg_atomic_uint64 current_wbucket;
pg_atomic_uint64 prev_bucket_sec;
uint64 bucket_entry[MAX_BUCKETS];
TimestampTz bucket_start_time[MAX_BUCKETS]; /* start time of the bucket */
int hash_tranche_id;
void *raw_dsa_area; /* DSA area pointer to store query texts.
* dshash also lives in this memory when
@ -400,16 +397,9 @@ typedef struct pgsmSharedState
* hash table handle. can be either classic shared memory hash or dshash
* (if we are using USE_DYNAMIC_HASH)
*/
MemoryContext pgsm_mem_cxt;
/*
* context to store stats in local memory until they are pushed to shared
* hash
*/
int resp_calls[MAX_RESPONSE_BUCKET + 2]; /* execution time's in
* msec; including 2
* outlier buckets */
bool pgsm_oom;
TimestampTz bucket_start_time[]; /* start time of the bucket */
} pgsmSharedState;
typedef struct pgsmLocalState
@ -418,6 +408,8 @@ typedef struct pgsmLocalState
dsa_area *dsa; /* local dsa area for backend attached to the
* dsa area created by postmaster at startup. */
PGSM_HASH_TABLE *shared_hash;
MemoryContext pgsm_mem_cxt;
} pgsmLocalState;
#if PG_VERSION_NUM < 140000
@ -479,6 +471,7 @@ void pgsm_startup(void);
/* hash_query.c */
void pgsm_startup(void);
MemoryContext GetPgsmMemoryContext(void);
/* guc.c */
void init_guc(void);

View File

@ -2,7 +2,7 @@ CREATE EXTENSION pg_stat_monitor;
SELECT pg_stat_monitor_version();
pg_stat_monitor_version
-------------------------
2.0.0
2.0.1
(1 row)
DROP EXTENSION pg_stat_monitor;

View File

@ -33,7 +33,7 @@ It provides all the features of pg_stat_statment plus its own feature set.
%build
sed -i 's:PG_CONFIG = pg_config:PG_CONFIG = /usr/pgsql-%{pgrel}/bin/pg_config:' Makefile
sed -i 's:PG_CONFIG ?= pg_config:PG_CONFIG = /usr/pgsql-%{pgrel}/bin/pg_config:' Makefile
%{__make} USE_PGXS=1 %{?_smp_mflags}