feat: add housekeeper task interceptor trigger and update docs

This commit is contained in:
Maksym Buz
2026-04-29 17:12:18 +00:00
parent a88cee43b6
commit 59b2780125
13 changed files with 158966 additions and 148395 deletions

15
postgresql/CHANGELOG.md Normal file
View File

@@ -0,0 +1,15 @@
# Changelog
All notable changes to this project will be documented in this file.
## [7-2] - 2026-04-29
### Added
- **Housekeeper Interceptor**: Added a PostgreSQL `BEFORE INSERT` trigger to the `housekeeper` table. This trigger dynamically checks `partitions.config` and silently discards Housekeeper tasks (inserts) for any tables managed by the partitioning system. This prevents Zabbix from filling the `housekeeper` table with unnecessary tasks, eliminating Sequential Scans and Table Bloat on the `housekeeper` table, while still allowing tasks for unpartitioned tables (like `events`) to be recorded normally.
## [7-1] - Previous Release
### Added
- Zabbix 7.0 and 7.4 compatibility.
- Special handling for the `auditlog` table primary key changes in Zabbix 7.0+.
- Dynamic creation of partitions and retention management logic.

View File

@@ -22,7 +22,7 @@ CREATE TABLE IF NOT EXISTS partitions.version (
description text description text
); );
INSERT INTO partitions.version (version, description) VALUES ('7-1', 'Zabbix 7.4 and 7.0 compatible version') INSERT INTO partitions.version (version, description) VALUES ('7-2', 'Added housekeeper task interceptor trigger to drop tasks for partitioned tables')
ON CONFLICT (version) DO NOTHING; ON CONFLICT (version) DO NOTHING;
-- Default configuration for Zabbix tables (adjust as needed) -- Default configuration for Zabbix tables (adjust as needed)

View File

@@ -226,3 +226,14 @@ BEGIN
END LOOP; END LOOP;
END; END;
$$; $$;
-- Trigger function to silently discard housekeeper tasks for partitioned tables
CREATE OR REPLACE FUNCTION partitions.housekeeper_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF EXISTS (SELECT 1 FROM partitions.config WHERE table_name = NEW.tablename) THEN
RETURN NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

View File

@@ -57,3 +57,10 @@ BEGIN
END IF; END IF;
END LOOP; END LOOP;
END $$; END $$;
-- Attach trigger to housekeeper table to silently discard tasks for partitioned tables
DROP TRIGGER IF EXISTS housekeeper_filter ON housekeeper;
CREATE TRIGGER housekeeper_filter
BEFORE INSERT ON housekeeper
FOR EACH ROW
EXECUTE FUNCTION partitions.housekeeper_insert_trigger();

View File

@@ -0,0 +1,69 @@
-- ============================================================================
-- Reverts Zabbix partitioned tables back to standard non-partitioned tables.
-- Existing partitioned tables will be renamed to *_part (data is preserved).
-- ============================================================================
DO $$
DECLARE
v_row record;
v_table text;
v_part_table text;
v_schema text;
BEGIN
FOR v_row IN SELECT * FROM partitions.config LOOP
v_table := v_row.table_name;
v_part_table := v_table || '_part';
-- Determine schema of the partitioned table
SELECT n.nspname INTO v_schema
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = v_table AND c.relkind = 'p';
IF v_schema IS NOT NULL THEN
RAISE NOTICE 'Reverting partitioned table %...', v_table;
-- 1. Rename existing partitioned table to *_part
EXECUTE format('ALTER TABLE %I.%I RENAME TO %I', v_schema, v_table, v_part_table);
-- 2. Create standard (unpartitioned) replacement table based on the structure
IF v_table = 'auditlog' THEN
-- For auditlog, we need to try and restore the original single-column PK (auditid) if possible
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING DEFAULTS INCLUDING COMMENTS)', v_schema, v_table, v_schema, v_part_table);
BEGIN
EXECUTE format('ALTER TABLE %I.%I ADD PRIMARY KEY (auditid)', v_schema, v_table);
EXCEPTION WHEN others THEN
RAISE WARNING 'Failed to create primary key on auditlog, might already exist or duplicates present.';
END;
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_1 ON %I.%I (userid, clock)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_2 ON %I.%I (clock)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_3 ON %I.%I (resourcetype, resourceid)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_4 ON %I.%I (recordsetid)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_5 ON %I.%I (ip)', v_schema, v_table);
ELSE
-- For others, copy everything including indexes
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL)', v_schema, v_table, v_schema, v_part_table);
END IF;
RAISE NOTICE 'SUCCESS: % reverted to default. Partitioned data stored in % (You can DROP TABLE % CASCADE; later).', v_table, v_part_table, v_part_table;
ELSIF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'r') THEN
RAISE NOTICE 'Table % is already a regular table. Skipping.', v_table;
ELSE
RAISE WARNING 'Partitioned table % not found!', v_table;
END IF;
END LOOP;
-- Drop the housekeeper intercept trigger
DROP TRIGGER IF EXISTS housekeeper_filter ON housekeeper;
RAISE NOTICE '================================================================================';
RAISE NOTICE 'Undo complete. Partitioned tables have been renamed to *_part.';
RAISE NOTICE 'If you want to migrate your history back, you must do it manually:';
RAISE NOTICE ' INSERT INTO history SELECT * FROM history_part;';
RAISE NOTICE 'Once done, or if you do not need the data, drop the partitioned tables:';
RAISE NOTICE ' DROP TABLE history_part CASCADE;';
RAISE NOTICE 'After that, you can safely remove the partitions infrastructure:';
RAISE NOTICE ' DROP SCHEMA partitions CASCADE;';
RAISE NOTICE '================================================================================';
END $$;

View File

@@ -21,6 +21,8 @@ This is the declarative partitioning implementation for Zabbix `history*`, `tren
- [Implementation Details](#implementation-details) - [Implementation Details](#implementation-details)
- [`auditlog` Table](#auditlog-table) - [`auditlog` Table](#auditlog-table)
- [Converting Existing Tables](#converting-existing-tables) - [Converting Existing Tables](#converting-existing-tables)
- [PostgreSQL Tuning](#postgresql-tuning)
- [Uninstall / Reverting](#uninstall--reverting)
- [Upgrades](#upgrades) - [Upgrades](#upgrades)
## Architecture ## Architecture
@@ -267,9 +269,59 @@ The enablement script guarantees practically zero downtime by automatically rena
* New data flows into the new partitioned tables immediately. * New data flows into the new partitioned tables immediately.
* Old data remains accessible in `table_name_old` for manual lookup or migration if required. * Old data remains accessible in `table_name_old` for manual lookup or migration if required.
## Upgrades ### Housekeeper Interceptor
Even when Zabbix Housekeeping is disabled in the UI for History and Trends, the Zabbix Server daemon may still generate and insert tasks into the `housekeeper` table (e.g., when an item or trigger is deleted, it schedules the deletion of its historical data). Without intervention, this results in the `housekeeper` table bloating massively over time, leading to slow sequential scans and `autovacuum` overhead.
When upgrading Zabbix: To prevent this, this extension installs a `BEFORE INSERT` trigger on the `housekeeper` table.
* When Zabbix attempts to insert a housekeeper task, the trigger intercepts it and checks if the target table is managed in `partitions.config`.
* If the table is partitioned (like `history`), the trigger **silently discards the insert** (`RETURNS NULL`), preventing disk I/O and table bloat entirely.
* If the table is not partitioned (like `events` or `sessions`), the task is allowed to be recorded and is cleaned up naturally by Zabbix.
## PostgreSQL Tuning
Before or immediately after enabling partitioning, you should tune your `postgresql.conf`. The standard configuration is not optimized for partitioned tables and might cause performance degradation or out-of-memory errors.
| Parameter | Recommended | Description |
|-----------|-------------|-------------|
| `max_locks_per_transaction`| `512` (or higher) | **Requires DB Restart.** Default is `64`, which is far too low. PostgreSQL lock tables per partition. With many partitioned tables (e.g., history x 30 days), operations like `pg_dump`, `VACUUM`, or queries crossing multiple boundaries will fail with *“out of shared memory”*. |
| `jit` | `off` | **Highly Recommended.** JIT adds overhead to query planning. With many partitions, JIT can drastically increase CPU usage as PostgreSQL attempts to optimize simple queries across dozens of partitions. |
**Default parameters to verify:**
The following are usually set correctly by default, but you should verify them just in case:
* `enable_partition_pruning = on` : **Critical.** Ensures PostgreSQL only queries the necessary partitions instead of scanning everything.
* `enable_partitionwise_join = off` : Zabbix does not do massive joins on history tables; enabling this only wastes planner CPU time.
* `enable_partitionwise_aggregate = off` : Zabbix doesn't perform complex DB-side `GROUP BY` aggregations on history. Leave it disabled.
## Uninstall / Reverting
If you wish to stop using partitioning and revert back to standard, unpartitioned tables without data loss, carefully follow these steps.
> [!CAUTION]
> Reverting partitioning replaces your partitioned tables with standard empty tables. If you need to retain data from the partitioned period, you must manually migrate it before dropping the partition sets. **Always stop Zabbix Server before proceeding.**
1. **Stop Zabbix Server** to prevent new data from being inserted during the transition.
2. **Execute Undo Script:** Run the `04_undo_partitioning.sql` script to recreate non-partitioned tables matching your original Zabbix schema. This script will rename your current partitioned tables to `*_part` (`history_part`, `trends_part`, etc.) and automatically create native, clean tables (`history`, `trends`) in their place.
```bash
psql -h $DB_HOST -U zbxpart_admin -d zabbix -f 04_undo_partitioning.sql
```
3. **Data Migration (Optional):** If you want to keep the metrics collected during the partitioned period, you must manually insert them into the newly created regular tables. This step can take hours depending on table sizes.
```sql
INSERT INTO history SELECT * FROM history_part;
INSERT INTO trends SELECT * FROM trends_part;
-- Repeat for all tables you wish to restore
```
4. **Cleanup:** Once you have migrated the data you need (or if you don't need it at all), you can drop the heavy partitioned tables and remove the partitioning extensions completely.
```sql
DROP TABLE history_part CASCADE;
DROP TABLE history_uint_part CASCADE;
-- Repeat for all *_part tables ...
-- To drop the automatic maintenance infrastructure:
DROP SCHEMA partitions CASCADE;
```
5. **Start Zabbix Server & Re-enable Housekeeper:** Once the tables are replaced, you can start the server. *Don't forget to re-enable Housekeeping for History and Trends in the Zabbix UI!*
## Upgrades
1. **Backup**: Ensure a full database backup exists. 1. **Backup**: Ensure a full database backup exists.
2. **Compatibility**: Zabbix upgrade scripts may attempt to `ALTER` tables. PostgreSQL supports `ALTER TABLE` on partitioned tables for adding columns, which propagates to partitions. 2. **Compatibility**: Zabbix upgrade scripts may attempt to `ALTER` tables. PostgreSQL supports `ALTER TABLE` on partitioned tables for adding columns, which propagates to partitions.
3. **Failure Scenarios**: If an upgrade script fails due to partitioning, the table may need to be temporarily reverted or the partition structure manually adjusted. 3. **Failure Scenarios**: If an upgrade script fails due to partitioning, the table may need to be temporarily reverted or the partition structure manually adjusted.

View File

@@ -36,6 +36,7 @@ The solution is divided into a series of SQL scripts that must be executed seque
* `drop_old_partitions()`: Iterates over existing child partitions (using `pg_inherits`) and calculates their age based on their suffix. Drops those older than the defined `keep_history` policy. * `drop_old_partitions()`: Iterates over existing child partitions (using `pg_inherits`) and calculates their age based on their suffix. Drops those older than the defined `keep_history` policy.
* `maintain_table()`: The orchestrator for a single table. It calculates the necessary UTC timestamps, calls `create_partition()` to build the future buffer, calls `create_partition()` recursively backward to cover the retention period, and finally calls `drop_old_partitions()`. * `maintain_table()`: The orchestrator for a single table. It calculates the necessary UTC timestamps, calls `create_partition()` to build the future buffer, calls `create_partition()` recursively backward to cover the retention period, and finally calls `drop_old_partitions()`.
* `run_maintenance()`: The global loop that iterates through `partitions.config` and triggers `maintain_table()` for every configured Zabbix table. * `run_maintenance()`: The global loop that iterates through `partitions.config` and triggers `maintain_table()` for every configured Zabbix table.
* `housekeeper_insert_trigger()`: A trigger function that intercepts `INSERT` queries into the Zabbix `housekeeper` table, silently discarding tasks for tables managed by the partitioning system (based on `partitions.config`).
### 3. `02_enable_partitioning.sql` ### 3. `02_enable_partitioning.sql`
* **Purpose:** The migration script that actually executes the partition conversion on the live database. * **Purpose:** The migration script that actually executes the partition conversion on the live database.
@@ -44,6 +45,7 @@ The solution is divided into a series of SQL scripts that must be executed seque
* It takes the original Zabbix table (e.g., `history`) and renames it to `history_old` (`ALTER TABLE ... RENAME TO ...`). * It takes the original Zabbix table (e.g., `history`) and renames it to `history_old` (`ALTER TABLE ... RENAME TO ...`).
* It immediately creates a new partitioned table with the original name, inheriting the exact structure of the old table (`CREATE TABLE ... (LIKE ... INCLUDING ALL) PARTITION BY RANGE (clock)`). * It immediately creates a new partitioned table with the original name, inheriting the exact structure of the old table (`CREATE TABLE ... (LIKE ... INCLUDING ALL) PARTITION BY RANGE (clock)`).
* It triggers the first maintenance run so new incoming data has immediate partitions to land in. * It triggers the first maintenance run so new incoming data has immediate partitions to land in.
* It attaches the `housekeeper_filter` trigger to the `housekeeper` table to prevent Zabbix from inserting garbage tasks for the partitioned tables.
### 4. `03_monitoring_view.sql` ### 4. `03_monitoring_view.sql`
* **Purpose:** Provides an easy-to-read observability layer. * **Purpose:** Provides an easy-to-read observability layer.

View File

@@ -86,6 +86,8 @@ CREATE TABLE hosts (
vendor_version varchar(32) DEFAULT '' NOT NULL, vendor_version varchar(32) DEFAULT '' NOT NULL,
proxy_groupid bigint NULL, proxy_groupid bigint NULL,
monitored_by integer DEFAULT '0' NOT NULL, monitored_by integer DEFAULT '0' NOT NULL,
wizard_ready integer DEFAULT '0' NOT NULL,
readme text DEFAULT '' NOT NULL,
PRIMARY KEY (hostid) PRIMARY KEY (hostid)
); );
CREATE INDEX hosts_1 ON hosts (host); CREATE INDEX hosts_1 ON hosts (host);
@@ -360,6 +362,20 @@ CREATE TABLE media_type (
PRIMARY KEY (mediatypeid) PRIMARY KEY (mediatypeid)
); );
CREATE UNIQUE INDEX media_type_1 ON media_type (name); CREATE UNIQUE INDEX media_type_1 ON media_type (name);
CREATE TABLE media_type_oauth (
mediatypeid bigint NOT NULL,
redirection_url varchar(2048) DEFAULT '' NOT NULL,
client_id varchar(255) DEFAULT '' NOT NULL,
client_secret varchar(255) DEFAULT '' NOT NULL,
authorization_url varchar(2048) DEFAULT '' NOT NULL,
tokens_status integer DEFAULT '0' NOT NULL,
access_token text DEFAULT '' NOT NULL,
access_token_updated integer DEFAULT '0' NOT NULL,
access_expires_in integer DEFAULT '0' NOT NULL,
refresh_token text DEFAULT '' NOT NULL,
token_url varchar(2048) DEFAULT '' NOT NULL,
PRIMARY KEY (mediatypeid)
);
CREATE TABLE media_type_param ( CREATE TABLE media_type_param (
mediatype_paramid bigint NOT NULL, mediatype_paramid bigint NOT NULL,
mediatypeid bigint NOT NULL, mediatypeid bigint NOT NULL,
@@ -570,132 +586,6 @@ CREATE TABLE conditions (
PRIMARY KEY (conditionid) PRIMARY KEY (conditionid)
); );
CREATE INDEX conditions_1 ON conditions (actionid); CREATE INDEX conditions_1 ON conditions (actionid);
CREATE TABLE config (
configid bigint NOT NULL,
work_period varchar(255) DEFAULT '1-5,09:00-18:00' NOT NULL,
alert_usrgrpid bigint NULL,
default_theme varchar(128) DEFAULT 'blue-theme' NOT NULL,
authentication_type integer DEFAULT '0' NOT NULL,
discovery_groupid bigint NULL,
max_in_table integer DEFAULT '50' NOT NULL,
search_limit integer DEFAULT '1000' NOT NULL,
severity_color_0 varchar(6) DEFAULT '97AAB3' NOT NULL,
severity_color_1 varchar(6) DEFAULT '7499FF' NOT NULL,
severity_color_2 varchar(6) DEFAULT 'FFC859' NOT NULL,
severity_color_3 varchar(6) DEFAULT 'FFA059' NOT NULL,
severity_color_4 varchar(6) DEFAULT 'E97659' NOT NULL,
severity_color_5 varchar(6) DEFAULT 'E45959' NOT NULL,
severity_name_0 varchar(32) DEFAULT 'Not classified' NOT NULL,
severity_name_1 varchar(32) DEFAULT 'Information' NOT NULL,
severity_name_2 varchar(32) DEFAULT 'Warning' NOT NULL,
severity_name_3 varchar(32) DEFAULT 'Average' NOT NULL,
severity_name_4 varchar(32) DEFAULT 'High' NOT NULL,
severity_name_5 varchar(32) DEFAULT 'Disaster' NOT NULL,
ok_period varchar(32) DEFAULT '5m' NOT NULL,
blink_period varchar(32) DEFAULT '2m' NOT NULL,
problem_unack_color varchar(6) DEFAULT 'CC0000' NOT NULL,
problem_ack_color varchar(6) DEFAULT 'CC0000' NOT NULL,
ok_unack_color varchar(6) DEFAULT '009900' NOT NULL,
ok_ack_color varchar(6) DEFAULT '009900' NOT NULL,
problem_unack_style integer DEFAULT '1' NOT NULL,
problem_ack_style integer DEFAULT '1' NOT NULL,
ok_unack_style integer DEFAULT '1' NOT NULL,
ok_ack_style integer DEFAULT '1' NOT NULL,
snmptrap_logging integer DEFAULT '1' NOT NULL,
server_check_interval integer DEFAULT '10' NOT NULL,
hk_events_mode integer DEFAULT '1' NOT NULL,
hk_events_trigger varchar(32) DEFAULT '365d' NOT NULL,
hk_events_internal varchar(32) DEFAULT '1d' NOT NULL,
hk_events_discovery varchar(32) DEFAULT '1d' NOT NULL,
hk_events_autoreg varchar(32) DEFAULT '1d' NOT NULL,
hk_services_mode integer DEFAULT '1' NOT NULL,
hk_services varchar(32) DEFAULT '365d' NOT NULL,
hk_audit_mode integer DEFAULT '1' NOT NULL,
hk_audit varchar(32) DEFAULT '31d' NOT NULL,
hk_sessions_mode integer DEFAULT '1' NOT NULL,
hk_sessions varchar(32) DEFAULT '365d' NOT NULL,
hk_history_mode integer DEFAULT '1' NOT NULL,
hk_history_global integer DEFAULT '0' NOT NULL,
hk_history varchar(32) DEFAULT '31d' NOT NULL,
hk_trends_mode integer DEFAULT '1' NOT NULL,
hk_trends_global integer DEFAULT '0' NOT NULL,
hk_trends varchar(32) DEFAULT '365d' NOT NULL,
default_inventory_mode integer DEFAULT '-1' NOT NULL,
custom_color integer DEFAULT '0' NOT NULL,
http_auth_enabled integer DEFAULT '0' NOT NULL,
http_login_form integer DEFAULT '0' NOT NULL,
http_strip_domains varchar(2048) DEFAULT '' NOT NULL,
http_case_sensitive integer DEFAULT '1' NOT NULL,
ldap_auth_enabled integer DEFAULT '0' NOT NULL,
ldap_case_sensitive integer DEFAULT '1' NOT NULL,
db_extension varchar(32) DEFAULT '' NOT NULL,
autoreg_tls_accept integer DEFAULT '1' NOT NULL,
compression_status integer DEFAULT '0' NOT NULL,
compress_older varchar(32) DEFAULT '7d' NOT NULL,
instanceid varchar(32) DEFAULT '' NOT NULL,
saml_auth_enabled integer DEFAULT '0' NOT NULL,
saml_case_sensitive integer DEFAULT '0' NOT NULL,
default_lang varchar(5) DEFAULT 'en_US' NOT NULL,
default_timezone varchar(50) DEFAULT 'system' NOT NULL,
login_attempts integer DEFAULT '5' NOT NULL,
login_block varchar(32) DEFAULT '30s' NOT NULL,
show_technical_errors integer DEFAULT '0' NOT NULL,
validate_uri_schemes integer DEFAULT '1' NOT NULL,
uri_valid_schemes varchar(255) DEFAULT 'http,https,ftp,file,mailto,tel,ssh' NOT NULL,
x_frame_options varchar(255) DEFAULT 'SAMEORIGIN' NOT NULL,
iframe_sandboxing_enabled integer DEFAULT '1' NOT NULL,
iframe_sandboxing_exceptions varchar(255) DEFAULT '' NOT NULL,
max_overview_table_size integer DEFAULT '50' NOT NULL,
history_period varchar(32) DEFAULT '24h' NOT NULL,
period_default varchar(32) DEFAULT '1h' NOT NULL,
max_period varchar(32) DEFAULT '2y' NOT NULL,
socket_timeout varchar(32) DEFAULT '3s' NOT NULL,
connect_timeout varchar(32) DEFAULT '3s' NOT NULL,
media_type_test_timeout varchar(32) DEFAULT '65s' NOT NULL,
script_timeout varchar(32) DEFAULT '60s' NOT NULL,
item_test_timeout varchar(32) DEFAULT '60s' NOT NULL,
session_key varchar(32) DEFAULT '' NOT NULL,
url varchar(2048) DEFAULT '' NOT NULL,
report_test_timeout varchar(32) DEFAULT '60s' NOT NULL,
dbversion_status text DEFAULT '' NOT NULL,
hk_events_service varchar(32) DEFAULT '1d' NOT NULL,
passwd_min_length integer DEFAULT '8' NOT NULL,
passwd_check_rules integer DEFAULT '8' NOT NULL,
auditlog_enabled integer DEFAULT '1' NOT NULL,
ha_failover_delay varchar(32) DEFAULT '1m' NOT NULL,
geomaps_tile_provider varchar(255) DEFAULT '' NOT NULL,
geomaps_tile_url varchar(2048) DEFAULT '' NOT NULL,
geomaps_max_zoom integer DEFAULT '0' NOT NULL,
geomaps_attribution varchar(1024) DEFAULT '' NOT NULL,
vault_provider integer DEFAULT '0' NOT NULL,
ldap_userdirectoryid bigint DEFAULT NULL NULL,
server_status text DEFAULT '' NOT NULL,
jit_provision_interval varchar(32) DEFAULT '1h' NOT NULL,
saml_jit_status integer DEFAULT '0' NOT NULL,
ldap_jit_status integer DEFAULT '0' NOT NULL,
disabled_usrgrpid bigint DEFAULT NULL NULL,
timeout_zabbix_agent varchar(255) DEFAULT '3s' NOT NULL,
timeout_simple_check varchar(255) DEFAULT '3s' NOT NULL,
timeout_snmp_agent varchar(255) DEFAULT '3s' NOT NULL,
timeout_external_check varchar(255) DEFAULT '3s' NOT NULL,
timeout_db_monitor varchar(255) DEFAULT '3s' NOT NULL,
timeout_http_agent varchar(255) DEFAULT '3s' NOT NULL,
timeout_ssh_agent varchar(255) DEFAULT '3s' NOT NULL,
timeout_telnet_agent varchar(255) DEFAULT '3s' NOT NULL,
timeout_script varchar(255) DEFAULT '3s' NOT NULL,
auditlog_mode integer DEFAULT '1' NOT NULL,
mfa_status integer DEFAULT '0' NOT NULL,
mfaid bigint NULL,
software_update_checkid varchar(32) DEFAULT '' NOT NULL,
software_update_check_data text DEFAULT '' NOT NULL,
timeout_browser varchar(255) DEFAULT '60s' NOT NULL,
PRIMARY KEY (configid)
);
CREATE INDEX config_1 ON config (alert_usrgrpid);
CREATE INDEX config_2 ON config (discovery_groupid);
CREATE INDEX config_3 ON config (ldap_userdirectoryid);
CREATE INDEX config_4 ON config (disabled_usrgrpid);
CREATE INDEX config_5 ON config (mfaid);
CREATE TABLE triggers ( CREATE TABLE triggers (
triggerid bigint NOT NULL, triggerid bigint NOT NULL,
expression varchar(2048) DEFAULT '' NOT NULL, expression varchar(2048) DEFAULT '' NOT NULL,
@@ -825,6 +715,18 @@ CREATE TABLE hostmacro (
PRIMARY KEY (hostmacroid) PRIMARY KEY (hostmacroid)
); );
CREATE UNIQUE INDEX hostmacro_1 ON hostmacro (hostid,macro); CREATE UNIQUE INDEX hostmacro_1 ON hostmacro (hostid,macro);
CREATE TABLE hostmacro_config (
hostmacroid bigint NOT NULL,
type integer DEFAULT '0' NOT NULL,
priority integer DEFAULT '0' NOT NULL,
section_name varchar(255) DEFAULT '' NOT NULL,
label varchar(255) DEFAULT '' NOT NULL,
description text DEFAULT '' NOT NULL,
required integer DEFAULT '0' NOT NULL,
regex varchar(255) DEFAULT '' NOT NULL,
options text DEFAULT '' NOT NULL,
PRIMARY KEY (hostmacroid)
);
CREATE TABLE hosts_groups ( CREATE TABLE hosts_groups (
hostgroupid bigint NOT NULL, hostgroupid bigint NOT NULL,
hostid bigint NOT NULL, hostid bigint NOT NULL,
@@ -956,6 +858,9 @@ CREATE TABLE sysmaps (
userid bigint NOT NULL, userid bigint NOT NULL,
private integer DEFAULT '1' NOT NULL, private integer DEFAULT '1' NOT NULL,
show_suppressed integer DEFAULT '0' NOT NULL, show_suppressed integer DEFAULT '0' NOT NULL,
background_scale integer DEFAULT '1' NOT NULL,
show_element_label integer DEFAULT '1' NOT NULL,
show_link_label integer DEFAULT '1' NOT NULL,
PRIMARY KEY (sysmapid) PRIMARY KEY (sysmapid)
); );
CREATE UNIQUE INDEX sysmaps_1 ON sysmaps (name); CREATE UNIQUE INDEX sysmaps_1 ON sysmaps (name);
@@ -982,6 +887,8 @@ CREATE TABLE sysmaps_elements (
viewtype integer DEFAULT '0' NOT NULL, viewtype integer DEFAULT '0' NOT NULL,
use_iconmap integer DEFAULT '1' NOT NULL, use_iconmap integer DEFAULT '1' NOT NULL,
evaltype integer DEFAULT '0' NOT NULL, evaltype integer DEFAULT '0' NOT NULL,
show_label integer DEFAULT '-1' NOT NULL,
zindex integer DEFAULT '0' NOT NULL,
PRIMARY KEY (selementid) PRIMARY KEY (selementid)
); );
CREATE INDEX sysmaps_elements_1 ON sysmaps_elements (sysmapid); CREATE INDEX sysmaps_elements_1 ON sysmaps_elements (sysmapid);
@@ -997,11 +904,15 @@ CREATE TABLE sysmaps_links (
drawtype integer DEFAULT '0' NOT NULL, drawtype integer DEFAULT '0' NOT NULL,
color varchar(6) DEFAULT '000000' NOT NULL, color varchar(6) DEFAULT '000000' NOT NULL,
label varchar(2048) DEFAULT '' NOT NULL, label varchar(2048) DEFAULT '' NOT NULL,
show_label integer DEFAULT '-1' NOT NULL,
indicator_type integer DEFAULT '0' NOT NULL,
itemid bigint NULL,
PRIMARY KEY (linkid) PRIMARY KEY (linkid)
); );
CREATE INDEX sysmaps_links_1 ON sysmaps_links (sysmapid); CREATE INDEX sysmaps_links_1 ON sysmaps_links (sysmapid);
CREATE INDEX sysmaps_links_2 ON sysmaps_links (selementid1); CREATE INDEX sysmaps_links_2 ON sysmaps_links (selementid1);
CREATE INDEX sysmaps_links_3 ON sysmaps_links (selementid2); CREATE INDEX sysmaps_links_3 ON sysmaps_links (selementid2);
CREATE INDEX sysmaps_links_4 ON sysmaps_links (itemid);
CREATE TABLE sysmaps_link_triggers ( CREATE TABLE sysmaps_link_triggers (
linktriggerid bigint NOT NULL, linktriggerid bigint NOT NULL,
linkid bigint NOT NULL, linkid bigint NOT NULL,
@@ -1012,6 +923,18 @@ CREATE TABLE sysmaps_link_triggers (
); );
CREATE UNIQUE INDEX sysmaps_link_triggers_1 ON sysmaps_link_triggers (linkid,triggerid); CREATE UNIQUE INDEX sysmaps_link_triggers_1 ON sysmaps_link_triggers (linkid,triggerid);
CREATE INDEX sysmaps_link_triggers_2 ON sysmaps_link_triggers (triggerid); CREATE INDEX sysmaps_link_triggers_2 ON sysmaps_link_triggers (triggerid);
CREATE TABLE sysmap_link_threshold (
linkthresholdid bigint NOT NULL,
linkid bigint NOT NULL,
drawtype integer DEFAULT '0' NOT NULL,
color varchar(6) DEFAULT '000000' NOT NULL,
type integer DEFAULT '0' NOT NULL,
threshold varchar(255) DEFAULT '' NOT NULL,
pattern varchar(255) DEFAULT '' NOT NULL,
sortorder integer DEFAULT '0' NOT NULL,
PRIMARY KEY (linkthresholdid)
);
CREATE INDEX sysmap_link_threshold_1 ON sysmap_link_threshold (linkid);
CREATE TABLE sysmap_element_url ( CREATE TABLE sysmap_element_url (
sysmapelementurlid bigint NOT NULL, sysmapelementurlid bigint NOT NULL,
selementid bigint NOT NULL, selementid bigint NOT NULL,
@@ -1197,7 +1120,6 @@ CREATE TABLE proxy_history (
write_clock integer DEFAULT '0' NOT NULL, write_clock integer DEFAULT '0' NOT NULL,
PRIMARY KEY (id) PRIMARY KEY (id)
); );
CREATE INDEX proxy_history_1 ON proxy_history (clock);
CREATE INDEX proxy_history_2 ON proxy_history (write_clock); CREATE INDEX proxy_history_2 ON proxy_history (write_clock);
CREATE TABLE proxy_dhistory ( CREATE TABLE proxy_dhistory (
id bigint NOT NULL, id bigint NOT NULL,
@@ -1474,21 +1396,23 @@ CREATE UNIQUE INDEX images_1 ON images (name);
CREATE TABLE item_discovery ( CREATE TABLE item_discovery (
itemdiscoveryid bigint NOT NULL, itemdiscoveryid bigint NOT NULL,
itemid bigint NOT NULL, itemid bigint NOT NULL,
parent_itemid bigint NOT NULL, parent_itemid bigint NULL,
key_ varchar(2048) DEFAULT '' NOT NULL, key_ varchar(2048) DEFAULT '' NOT NULL,
lastcheck integer DEFAULT '0' NOT NULL, lastcheck integer DEFAULT '0' NOT NULL,
ts_delete integer DEFAULT '0' NOT NULL, ts_delete integer DEFAULT '0' NOT NULL,
status integer DEFAULT '0' NOT NULL, status integer DEFAULT '0' NOT NULL,
disable_source integer DEFAULT '0' NOT NULL, disable_source integer DEFAULT '0' NOT NULL,
ts_disable integer DEFAULT '0' NOT NULL, ts_disable integer DEFAULT '0' NOT NULL,
lldruleid bigint NULL,
PRIMARY KEY (itemdiscoveryid) PRIMARY KEY (itemdiscoveryid)
); );
CREATE UNIQUE INDEX item_discovery_1 ON item_discovery (itemid,parent_itemid); CREATE UNIQUE INDEX item_discovery_1 ON item_discovery (itemid,parent_itemid);
CREATE INDEX item_discovery_2 ON item_discovery (parent_itemid); CREATE INDEX item_discovery_2 ON item_discovery (parent_itemid);
CREATE INDEX item_discovery_3 ON item_discovery (lldruleid);
CREATE TABLE host_discovery ( CREATE TABLE host_discovery (
hostid bigint NOT NULL, hostid bigint NOT NULL,
parent_hostid bigint NULL, parent_hostid bigint NULL,
parent_itemid bigint NULL, lldruleid bigint NULL,
host varchar(128) DEFAULT '' NOT NULL, host varchar(128) DEFAULT '' NOT NULL,
lastcheck integer DEFAULT '0' NOT NULL, lastcheck integer DEFAULT '0' NOT NULL,
ts_delete integer DEFAULT '0' NOT NULL, ts_delete integer DEFAULT '0' NOT NULL,
@@ -1498,7 +1422,7 @@ CREATE TABLE host_discovery (
PRIMARY KEY (hostid) PRIMARY KEY (hostid)
); );
CREATE INDEX host_discovery_1 ON host_discovery (parent_hostid); CREATE INDEX host_discovery_1 ON host_discovery (parent_hostid);
CREATE INDEX host_discovery_2 ON host_discovery (parent_itemid); CREATE INDEX host_discovery_2 ON host_discovery (lldruleid);
CREATE TABLE interface_discovery ( CREATE TABLE interface_discovery (
interfaceid bigint NOT NULL, interfaceid bigint NOT NULL,
parent_interfaceid bigint NOT NULL, parent_interfaceid bigint NOT NULL,
@@ -2483,13 +2407,36 @@ CREATE TABLE mfa_totp_secret (
); );
CREATE INDEX mfa_totp_secret_1 ON mfa_totp_secret (mfaid); CREATE INDEX mfa_totp_secret_1 ON mfa_totp_secret (mfaid);
CREATE INDEX mfa_totp_secret_2 ON mfa_totp_secret (userid); CREATE INDEX mfa_totp_secret_2 ON mfa_totp_secret (userid);
CREATE TABLE settings (
name varchar(255) NOT NULL,
type integer NOT NULL,
value_str text DEFAULT '' NOT NULL,
value_int integer DEFAULT '0' NOT NULL,
value_usrgrpid bigint NULL,
value_hostgroupid bigint NULL,
value_userdirectoryid bigint NULL,
value_mfaid bigint NULL,
PRIMARY KEY (name)
);
CREATE INDEX settings_2 ON settings (value_usrgrpid);
CREATE INDEX settings_3 ON settings (value_hostgroupid);
CREATE INDEX settings_4 ON settings (value_userdirectoryid);
CREATE INDEX settings_5 ON settings (value_mfaid);
CREATE TABLE lld_macro_export (
lld_macro_exportid bigint NOT NULL,
itemid bigint NOT NULL,
lld_macro varchar(255) DEFAULT '' NOT NULL,
value text DEFAULT '' NOT NULL,
PRIMARY KEY (lld_macro_exportid)
);
CREATE INDEX lld_macro_export_1 ON lld_macro_export (itemid);
CREATE TABLE dbversion ( CREATE TABLE dbversion (
dbversionid bigint NOT NULL, dbversionid bigint NOT NULL,
mandatory integer DEFAULT '0' NOT NULL, mandatory integer DEFAULT '0' NOT NULL,
optional integer DEFAULT '0' NOT NULL, optional integer DEFAULT '0' NOT NULL,
PRIMARY KEY (dbversionid) PRIMARY KEY (dbversionid)
); );
INSERT INTO dbversion VALUES ('1','7000000','7000029'); INSERT INTO dbversion VALUES ('1','7040000','7040009');
create or replace function changelog_hosts_insert() returns trigger as $$ create or replace function changelog_hosts_insert() returns trigger as $$
begin begin
insert into changelog (object,objectid,operation,clock) insert into changelog (object,objectid,operation,clock)
@@ -3164,6 +3111,7 @@ ALTER TABLE ONLY httpstepitem ADD CONSTRAINT c_httpstepitem_1 FOREIGN KEY (https
ALTER TABLE ONLY httpstepitem ADD CONSTRAINT c_httpstepitem_2 FOREIGN KEY (itemid) REFERENCES items (itemid); ALTER TABLE ONLY httpstepitem ADD CONSTRAINT c_httpstepitem_2 FOREIGN KEY (itemid) REFERENCES items (itemid);
ALTER TABLE ONLY httptestitem ADD CONSTRAINT c_httptestitem_1 FOREIGN KEY (httptestid) REFERENCES httptest (httptestid); ALTER TABLE ONLY httptestitem ADD CONSTRAINT c_httptestitem_1 FOREIGN KEY (httptestid) REFERENCES httptest (httptestid);
ALTER TABLE ONLY httptestitem ADD CONSTRAINT c_httptestitem_2 FOREIGN KEY (itemid) REFERENCES items (itemid); ALTER TABLE ONLY httptestitem ADD CONSTRAINT c_httptestitem_2 FOREIGN KEY (itemid) REFERENCES items (itemid);
ALTER TABLE ONLY media_type_oauth ADD CONSTRAINT c_media_type_oauth_1 FOREIGN KEY (mediatypeid) REFERENCES media_type (mediatypeid) ON DELETE CASCADE;
ALTER TABLE ONLY media_type_param ADD CONSTRAINT c_media_type_param_1 FOREIGN KEY (mediatypeid) REFERENCES media_type (mediatypeid) ON DELETE CASCADE; ALTER TABLE ONLY media_type_param ADD CONSTRAINT c_media_type_param_1 FOREIGN KEY (mediatypeid) REFERENCES media_type (mediatypeid) ON DELETE CASCADE;
ALTER TABLE ONLY media_type_message ADD CONSTRAINT c_media_type_message_1 FOREIGN KEY (mediatypeid) REFERENCES media_type (mediatypeid) ON DELETE CASCADE; ALTER TABLE ONLY media_type_message ADD CONSTRAINT c_media_type_message_1 FOREIGN KEY (mediatypeid) REFERENCES media_type (mediatypeid) ON DELETE CASCADE;
ALTER TABLE ONLY usrgrp ADD CONSTRAINT c_usrgrp_2 FOREIGN KEY (userdirectoryid) REFERENCES userdirectory (userdirectoryid); ALTER TABLE ONLY usrgrp ADD CONSTRAINT c_usrgrp_2 FOREIGN KEY (userdirectoryid) REFERENCES userdirectory (userdirectoryid);
@@ -3197,11 +3145,6 @@ ALTER TABLE ONLY optemplate ADD CONSTRAINT c_optemplate_1 FOREIGN KEY (operation
ALTER TABLE ONLY optemplate ADD CONSTRAINT c_optemplate_2 FOREIGN KEY (templateid) REFERENCES hosts (hostid); ALTER TABLE ONLY optemplate ADD CONSTRAINT c_optemplate_2 FOREIGN KEY (templateid) REFERENCES hosts (hostid);
ALTER TABLE ONLY opconditions ADD CONSTRAINT c_opconditions_1 FOREIGN KEY (operationid) REFERENCES operations (operationid) ON DELETE CASCADE; ALTER TABLE ONLY opconditions ADD CONSTRAINT c_opconditions_1 FOREIGN KEY (operationid) REFERENCES operations (operationid) ON DELETE CASCADE;
ALTER TABLE ONLY conditions ADD CONSTRAINT c_conditions_1 FOREIGN KEY (actionid) REFERENCES actions (actionid) ON DELETE CASCADE; ALTER TABLE ONLY conditions ADD CONSTRAINT c_conditions_1 FOREIGN KEY (actionid) REFERENCES actions (actionid) ON DELETE CASCADE;
ALTER TABLE ONLY config ADD CONSTRAINT c_config_1 FOREIGN KEY (alert_usrgrpid) REFERENCES usrgrp (usrgrpid);
ALTER TABLE ONLY config ADD CONSTRAINT c_config_2 FOREIGN KEY (discovery_groupid) REFERENCES hstgrp (groupid);
ALTER TABLE ONLY config ADD CONSTRAINT c_config_3 FOREIGN KEY (ldap_userdirectoryid) REFERENCES userdirectory (userdirectoryid);
ALTER TABLE ONLY config ADD CONSTRAINT c_config_4 FOREIGN KEY (disabled_usrgrpid) REFERENCES usrgrp (usrgrpid);
ALTER TABLE ONLY config ADD CONSTRAINT c_config_5 FOREIGN KEY (mfaid) REFERENCES mfa (mfaid);
ALTER TABLE ONLY triggers ADD CONSTRAINT c_triggers_1 FOREIGN KEY (templateid) REFERENCES triggers (triggerid); ALTER TABLE ONLY triggers ADD CONSTRAINT c_triggers_1 FOREIGN KEY (templateid) REFERENCES triggers (triggerid);
ALTER TABLE ONLY trigger_depends ADD CONSTRAINT c_trigger_depends_1 FOREIGN KEY (triggerid_down) REFERENCES triggers (triggerid) ON DELETE CASCADE; ALTER TABLE ONLY trigger_depends ADD CONSTRAINT c_trigger_depends_1 FOREIGN KEY (triggerid_down) REFERENCES triggers (triggerid) ON DELETE CASCADE;
ALTER TABLE ONLY trigger_depends ADD CONSTRAINT c_trigger_depends_2 FOREIGN KEY (triggerid_up) REFERENCES triggers (triggerid) ON DELETE CASCADE; ALTER TABLE ONLY trigger_depends ADD CONSTRAINT c_trigger_depends_2 FOREIGN KEY (triggerid_up) REFERENCES triggers (triggerid) ON DELETE CASCADE;
@@ -3213,6 +3156,7 @@ ALTER TABLE ONLY graphs ADD CONSTRAINT c_graphs_3 FOREIGN KEY (ymax_itemid) REFE
ALTER TABLE ONLY graphs_items ADD CONSTRAINT c_graphs_items_1 FOREIGN KEY (graphid) REFERENCES graphs (graphid) ON DELETE CASCADE; ALTER TABLE ONLY graphs_items ADD CONSTRAINT c_graphs_items_1 FOREIGN KEY (graphid) REFERENCES graphs (graphid) ON DELETE CASCADE;
ALTER TABLE ONLY graphs_items ADD CONSTRAINT c_graphs_items_2 FOREIGN KEY (itemid) REFERENCES items (itemid) ON DELETE CASCADE; ALTER TABLE ONLY graphs_items ADD CONSTRAINT c_graphs_items_2 FOREIGN KEY (itemid) REFERENCES items (itemid) ON DELETE CASCADE;
ALTER TABLE ONLY hostmacro ADD CONSTRAINT c_hostmacro_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE; ALTER TABLE ONLY hostmacro ADD CONSTRAINT c_hostmacro_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE;
ALTER TABLE ONLY hostmacro_config ADD CONSTRAINT c_hostmacro_config_1 FOREIGN KEY (hostmacroid) REFERENCES hostmacro (hostmacroid) ON DELETE CASCADE;
ALTER TABLE ONLY hosts_groups ADD CONSTRAINT c_hosts_groups_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE; ALTER TABLE ONLY hosts_groups ADD CONSTRAINT c_hosts_groups_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE;
ALTER TABLE ONLY hosts_groups ADD CONSTRAINT c_hosts_groups_2 FOREIGN KEY (groupid) REFERENCES hstgrp (groupid) ON DELETE CASCADE; ALTER TABLE ONLY hosts_groups ADD CONSTRAINT c_hosts_groups_2 FOREIGN KEY (groupid) REFERENCES hstgrp (groupid) ON DELETE CASCADE;
ALTER TABLE ONLY hosts_templates ADD CONSTRAINT c_hosts_templates_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE; ALTER TABLE ONLY hosts_templates ADD CONSTRAINT c_hosts_templates_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE;
@@ -3241,8 +3185,10 @@ ALTER TABLE ONLY sysmaps_elements ADD CONSTRAINT c_sysmaps_elements_5 FOREIGN KE
ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_1 FOREIGN KEY (sysmapid) REFERENCES sysmaps (sysmapid) ON DELETE CASCADE; ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_1 FOREIGN KEY (sysmapid) REFERENCES sysmaps (sysmapid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_2 FOREIGN KEY (selementid1) REFERENCES sysmaps_elements (selementid) ON DELETE CASCADE; ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_2 FOREIGN KEY (selementid1) REFERENCES sysmaps_elements (selementid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_3 FOREIGN KEY (selementid2) REFERENCES sysmaps_elements (selementid) ON DELETE CASCADE; ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_3 FOREIGN KEY (selementid2) REFERENCES sysmaps_elements (selementid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmaps_links ADD CONSTRAINT c_sysmaps_links_4 FOREIGN KEY (itemid) REFERENCES items (itemid);
ALTER TABLE ONLY sysmaps_link_triggers ADD CONSTRAINT c_sysmaps_link_triggers_1 FOREIGN KEY (linkid) REFERENCES sysmaps_links (linkid) ON DELETE CASCADE; ALTER TABLE ONLY sysmaps_link_triggers ADD CONSTRAINT c_sysmaps_link_triggers_1 FOREIGN KEY (linkid) REFERENCES sysmaps_links (linkid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmaps_link_triggers ADD CONSTRAINT c_sysmaps_link_triggers_2 FOREIGN KEY (triggerid) REFERENCES triggers (triggerid) ON DELETE CASCADE; ALTER TABLE ONLY sysmaps_link_triggers ADD CONSTRAINT c_sysmaps_link_triggers_2 FOREIGN KEY (triggerid) REFERENCES triggers (triggerid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmap_link_threshold ADD CONSTRAINT c_sysmap_link_threshold_1 FOREIGN KEY (linkid) REFERENCES sysmaps_links (linkid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmap_element_url ADD CONSTRAINT c_sysmap_element_url_1 FOREIGN KEY (selementid) REFERENCES sysmaps_elements (selementid) ON DELETE CASCADE; ALTER TABLE ONLY sysmap_element_url ADD CONSTRAINT c_sysmap_element_url_1 FOREIGN KEY (selementid) REFERENCES sysmaps_elements (selementid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmap_url ADD CONSTRAINT c_sysmap_url_1 FOREIGN KEY (sysmapid) REFERENCES sysmaps (sysmapid) ON DELETE CASCADE; ALTER TABLE ONLY sysmap_url ADD CONSTRAINT c_sysmap_url_1 FOREIGN KEY (sysmapid) REFERENCES sysmaps (sysmapid) ON DELETE CASCADE;
ALTER TABLE ONLY sysmap_user ADD CONSTRAINT c_sysmap_user_1 FOREIGN KEY (sysmapid) REFERENCES sysmaps (sysmapid) ON DELETE CASCADE; ALTER TABLE ONLY sysmap_user ADD CONSTRAINT c_sysmap_user_1 FOREIGN KEY (sysmapid) REFERENCES sysmaps (sysmapid) ON DELETE CASCADE;
@@ -3276,9 +3222,10 @@ ALTER TABLE ONLY graph_discovery ADD CONSTRAINT c_graph_discovery_2 FOREIGN KEY
ALTER TABLE ONLY host_inventory ADD CONSTRAINT c_host_inventory_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE; ALTER TABLE ONLY host_inventory ADD CONSTRAINT c_host_inventory_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE;
ALTER TABLE ONLY item_discovery ADD CONSTRAINT c_item_discovery_1 FOREIGN KEY (itemid) REFERENCES items (itemid) ON DELETE CASCADE; ALTER TABLE ONLY item_discovery ADD CONSTRAINT c_item_discovery_1 FOREIGN KEY (itemid) REFERENCES items (itemid) ON DELETE CASCADE;
ALTER TABLE ONLY item_discovery ADD CONSTRAINT c_item_discovery_2 FOREIGN KEY (parent_itemid) REFERENCES items (itemid) ON DELETE CASCADE; ALTER TABLE ONLY item_discovery ADD CONSTRAINT c_item_discovery_2 FOREIGN KEY (parent_itemid) REFERENCES items (itemid) ON DELETE CASCADE;
ALTER TABLE ONLY item_discovery ADD CONSTRAINT c_item_discovery_3 FOREIGN KEY (lldruleid) REFERENCES items (itemid);
ALTER TABLE ONLY host_discovery ADD CONSTRAINT c_host_discovery_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE; ALTER TABLE ONLY host_discovery ADD CONSTRAINT c_host_discovery_1 FOREIGN KEY (hostid) REFERENCES hosts (hostid) ON DELETE CASCADE;
ALTER TABLE ONLY host_discovery ADD CONSTRAINT c_host_discovery_2 FOREIGN KEY (parent_hostid) REFERENCES hosts (hostid); ALTER TABLE ONLY host_discovery ADD CONSTRAINT c_host_discovery_2 FOREIGN KEY (parent_hostid) REFERENCES hosts (hostid);
ALTER TABLE ONLY host_discovery ADD CONSTRAINT c_host_discovery_3 FOREIGN KEY (parent_itemid) REFERENCES items (itemid); ALTER TABLE ONLY host_discovery ADD CONSTRAINT c_host_discovery_3 FOREIGN KEY (lldruleid) REFERENCES items (itemid);
ALTER TABLE ONLY interface_discovery ADD CONSTRAINT c_interface_discovery_1 FOREIGN KEY (interfaceid) REFERENCES interface (interfaceid) ON DELETE CASCADE; ALTER TABLE ONLY interface_discovery ADD CONSTRAINT c_interface_discovery_1 FOREIGN KEY (interfaceid) REFERENCES interface (interfaceid) ON DELETE CASCADE;
ALTER TABLE ONLY interface_discovery ADD CONSTRAINT c_interface_discovery_2 FOREIGN KEY (parent_interfaceid) REFERENCES interface (interfaceid) ON DELETE CASCADE; ALTER TABLE ONLY interface_discovery ADD CONSTRAINT c_interface_discovery_2 FOREIGN KEY (parent_interfaceid) REFERENCES interface (interfaceid) ON DELETE CASCADE;
ALTER TABLE ONLY profiles ADD CONSTRAINT c_profiles_1 FOREIGN KEY (userid) REFERENCES users (userid) ON DELETE CASCADE; ALTER TABLE ONLY profiles ADD CONSTRAINT c_profiles_1 FOREIGN KEY (userid) REFERENCES users (userid) ON DELETE CASCADE;
@@ -3405,3 +3352,8 @@ ALTER TABLE ONLY host_proxy ADD CONSTRAINT c_host_proxy_1 FOREIGN KEY (hostid) R
ALTER TABLE ONLY host_proxy ADD CONSTRAINT c_host_proxy_2 FOREIGN KEY (proxyid) REFERENCES proxy (proxyid); ALTER TABLE ONLY host_proxy ADD CONSTRAINT c_host_proxy_2 FOREIGN KEY (proxyid) REFERENCES proxy (proxyid);
ALTER TABLE ONLY mfa_totp_secret ADD CONSTRAINT c_mfa_totp_secret_1 FOREIGN KEY (mfaid) REFERENCES mfa (mfaid) ON DELETE CASCADE; ALTER TABLE ONLY mfa_totp_secret ADD CONSTRAINT c_mfa_totp_secret_1 FOREIGN KEY (mfaid) REFERENCES mfa (mfaid) ON DELETE CASCADE;
ALTER TABLE ONLY mfa_totp_secret ADD CONSTRAINT c_mfa_totp_secret_2 FOREIGN KEY (userid) REFERENCES users (userid) ON DELETE CASCADE; ALTER TABLE ONLY mfa_totp_secret ADD CONSTRAINT c_mfa_totp_secret_2 FOREIGN KEY (userid) REFERENCES users (userid) ON DELETE CASCADE;
ALTER TABLE ONLY settings ADD CONSTRAINT c_settings_2 FOREIGN KEY (value_usrgrpid) REFERENCES usrgrp (usrgrpid);
ALTER TABLE ONLY settings ADD CONSTRAINT c_settings_3 FOREIGN KEY (value_hostgroupid) REFERENCES hstgrp (groupid);
ALTER TABLE ONLY settings ADD CONSTRAINT c_settings_4 FOREIGN KEY (value_userdirectoryid) REFERENCES userdirectory (userdirectoryid);
ALTER TABLE ONLY settings ADD CONSTRAINT c_settings_5 FOREIGN KEY (value_mfaid) REFERENCES mfa (mfaid);
ALTER TABLE ONLY lld_macro_export ADD CONSTRAINT c_lld_macro_export_1 FOREIGN KEY (itemid) REFERENCES items (itemid) ON DELETE CASCADE;

View File

@@ -8,7 +8,7 @@ CREATE SCHEMA IF NOT EXISTS partitions;
-- Configuration table to store partitioning settings per table -- Configuration table to store partitioning settings per table
CREATE TABLE IF NOT EXISTS partitions.config ( CREATE TABLE IF NOT EXISTS partitions.config (
table_name text NOT NULL, table_name text NOT NULL,
period text NOT NULL CHECK (period IN ('day', 'week', 'month', 'year')), period text NOT NULL,
keep_history interval NOT NULL, keep_history interval NOT NULL,
future_partitions integer NOT NULL DEFAULT 5, future_partitions integer NOT NULL DEFAULT 5,
last_updated timestamp WITH TIME ZONE DEFAULT (now() AT TIME ZONE 'UTC'), last_updated timestamp WITH TIME ZONE DEFAULT (now() AT TIME ZONE 'UTC'),
@@ -22,8 +22,7 @@ CREATE TABLE IF NOT EXISTS partitions.version (
description text description text
); );
-- Set initial version INSERT INTO partitions.version (version, description) VALUES ('7-1', 'Zabbix 7.4 and 7.0 compatible version')
INSERT INTO partitions.version (version, description) VALUES ('1.0', 'Initial release')
ON CONFLICT (version) DO NOTHING; ON CONFLICT (version) DO NOTHING;
-- Default configuration for Zabbix tables (adjust as needed) -- Default configuration for Zabbix tables (adjust as needed)

View File

@@ -43,6 +43,8 @@ BEGIN
IF p_period = 'month' THEN IF p_period = 'month' THEN
v_suffix := to_char(p_start_time, 'YYYYMM'); v_suffix := to_char(p_start_time, 'YYYYMM');
ELSIF p_period LIKE '%hour%' THEN
v_suffix := to_char(p_start_time, 'YYYYMMDDHH24');
ELSE ELSE
v_suffix := to_char(p_start_time, 'YYYYMMDD'); v_suffix := to_char(p_start_time, 'YYYYMMDD');
END IF; END IF;
@@ -50,10 +52,15 @@ BEGIN
v_partition_name := p_parent_table || '_p' || v_suffix; v_partition_name := p_parent_table || '_p' || v_suffix;
IF NOT partitions.partition_exists(v_partition_name) THEN IF NOT partitions.partition_exists(v_partition_name) THEN
EXECUTE format( BEGIN
'CREATE TABLE %I.%I PARTITION OF %I.%I FOR VALUES FROM (%s) TO (%s)', EXECUTE format(
v_parent_schema, v_partition_name, v_parent_schema, p_parent_table, v_start_ts, v_end_ts 'CREATE TABLE %I.%I PARTITION OF %I.%I FOR VALUES FROM (%s) TO (%s)',
); v_parent_schema, v_partition_name, v_parent_schema, p_parent_table, v_start_ts, v_end_ts
);
EXCEPTION WHEN invalid_object_definition THEN
-- Ignore overlap errors (e.g., when transitioning from daily to hourly partitioning)
RAISE NOTICE 'Partition % overlaps with an existing partition. Skipping.', v_partition_name;
END;
END IF; END IF;
END; END;
$$; $$;
@@ -91,26 +98,47 @@ BEGIN
BEGIN BEGIN
IF length(v_suffix) = 6 THEN -- YYYYMM IF length(v_suffix) = 6 THEN -- YYYYMM
v_partition_date := timezone('UTC', to_timestamp(v_suffix || '01', 'YYYYMMDD')::timestamp without time zone); v_partition_date := timezone('UTC', to_timestamp(v_suffix || '01', 'YYYYMMDD')::timestamp without time zone);
-- For monthly, we check if the END of the month is older than retention? ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD
-- Or just strict retention. v_partition_date := timezone('UTC', to_timestamp(v_suffix, 'YYYYMMDD')::timestamp without time zone);
-- To be safe, adding 1 month to check vs cutoff. ELSIF length(v_suffix) = 10 THEN -- YYYYMMDDHH
IF extract(epoch from (v_partition_date + '1 month'::interval)) < v_cutoff_ts THEN v_partition_date := timezone('UTC', to_timestamp(v_suffix, 'YYYYMMDDHH24')::timestamp without time zone);
ELSE
CONTINUE; -- Ignore non-matching suffix lengths
END IF;
EXCEPTION WHEN OTHERS THEN
-- Safely ignore parsing errors for oddly named partitions
CONTINUE;
END;
-- Now check retention and execute DROP TABLE (so dropping errors are correctly raised!)
IF length(v_suffix) = 6 THEN -- YYYYMM
IF extract(epoch from (v_partition_date + '1 month'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately
END IF;
ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD
-- If period is weekly, the partition spans an entire week. Otherwise, it spans one day.
IF p_period = 'week' THEN
IF extract(epoch from (v_partition_date + '1 week'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name; RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name); EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately COMMIT; -- Release lock immediately
END IF; END IF;
ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD ELSE
v_partition_date := timezone('UTC', to_timestamp(v_suffix, 'YYYYMMDD')::timestamp without time zone);
IF extract(epoch from (v_partition_date + '1 day'::interval)) < v_cutoff_ts THEN IF extract(epoch from (v_partition_date + '1 day'::interval)) < v_cutoff_ts THEN
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name; RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name); EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately COMMIT; -- Release lock immediately
END IF; END IF;
END IF; END IF;
EXCEPTION WHEN OTHERS THEN ELSIF length(v_suffix) = 10 THEN -- YYYYMMDDHH
-- Ignore parsing errors for non-standard partitions IF extract(epoch from (v_partition_date + p_period::interval)) < v_cutoff_ts THEN
NULL; RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
END; EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
COMMIT; -- Release lock immediately
END IF;
END IF;
END LOOP; END LOOP;
END; END;
$$; $$;
@@ -145,8 +173,14 @@ BEGIN
v_start_time := date_trunc('month', now(), 'UTC'); v_start_time := date_trunc('month', now(), 'UTC');
-- Approximate 30 days per month (2592000 seconds) -- Approximate 30 days per month (2592000 seconds)
v_past_iterations := ceil(extract(epoch from p_keep_history) / 2592000)::integer; v_past_iterations := ceil(extract(epoch from p_keep_history) / 2592000)::integer;
ELSIF p_period LIKE '%hour%' THEN
v_period_interval := p_period::interval;
v_start_time := to_timestamp(floor(extract(epoch from now()) / extract(epoch from v_period_interval)) * extract(epoch from v_period_interval));
v_past_iterations := ceil(extract(epoch from p_keep_history) / extract(epoch from v_period_interval))::integer;
ELSE ELSE
RETURN; RAISE EXCEPTION 'Unsupported partitioning period: %', p_period;
END IF; END IF;
-- 1. Create Future Partitions (Current + Buffer) -- 1. Create Future Partitions (Current + Buffer)
@@ -192,3 +226,14 @@ BEGIN
END LOOP; END LOOP;
END; END;
$$; $$;
-- Trigger function to silently discard housekeeper tasks for partitioned tables
CREATE OR REPLACE FUNCTION partitions.housekeeper_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF EXISTS (SELECT 1 FROM partitions.config WHERE table_name = NEW.tablename) THEN
RETURN NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

View File

@@ -32,8 +32,11 @@ BEGIN
IF v_table = 'auditlog' THEN IF v_table = 'auditlog' THEN
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING DEFAULTS INCLUDING COMMENTS) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table); EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING DEFAULTS INCLUDING COMMENTS) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table);
EXECUTE format('ALTER TABLE %I.%I ADD PRIMARY KEY (auditid, clock)', v_schema, v_table); EXECUTE format('ALTER TABLE %I.%I ADD PRIMARY KEY (auditid, clock)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_1 ON %I.%I (userid, clock)', v_schema, v_table); EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_1 ON %I.%I (userid, clock)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_2 ON %I.%I (clock)', v_schema, v_table); EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_2 ON %I.%I (clock)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_3 ON %I.%I (resourcetype, resourceid)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_4 ON %I.%I (recordsetid)', v_schema, v_table);
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_5 ON %I.%I (ip)', v_schema, v_table);
ELSE ELSE
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table); EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table);
END IF; END IF;
@@ -54,3 +57,10 @@ BEGIN
END IF; END IF;
END LOOP; END LOOP;
END $$; END $$;
-- Attach trigger to housekeeper table to silently discard tasks for partitioned tables
DROP TRIGGER IF EXISTS housekeeper_filter ON housekeeper;
CREATE TRIGGER housekeeper_filter
BEFORE INSERT ON housekeeper
FOR EACH ROW
EXECUTE FUNCTION partitions.housekeeper_insert_trigger();

View File

@@ -2,19 +2,26 @@
-- Creates a view to monitor partition status and sizes. -- Creates a view to monitor partition status and sizes.
-- ============================================================================ -- ============================================================================
CREATE OR REPLACE VIEW partitions.monitoring AS DROP VIEW IF EXISTS partitions.monitoring;
CREATE VIEW partitions.monitoring AS
SELECT SELECT
parent.relname AS parent_table, parent.relname AS parent_table,
c.table_name, c.table_name,
c.period, c.period,
c.keep_history, c.keep_history,
c.future_partitions AS configured_future_partitions,
count(child.relname) AS partition_count, count(child.relname) AS partition_count,
count(child.relname) FILTER ( count(child.relname) FILTER (
WHERE WHERE
(c.period = 'day' AND child.relname > (parent.relname || '_p' || to_char(now(), 'YYYYMMDD'))) (c.period = 'day' AND child.relname > (parent.relname || '_p' || to_char(now() AT TIME ZONE 'UTC', 'YYYYMMDD')))
OR OR
(c.period = 'month' AND child.relname > (parent.relname || '_p' || to_char(now(), 'YYYYMM'))) (c.period = 'month' AND child.relname > (parent.relname || '_p' || to_char(now() AT TIME ZONE 'UTC', 'YYYYMM')))
) AS future_partitions, OR
(c.period = 'week' AND child.relname > (parent.relname || '_p' || to_char(date_trunc('week', now() AT TIME ZONE 'UTC'), 'YYYYMMDD')))
OR
(c.period LIKE '%hour%' AND child.relname > (parent.relname || '_p' || to_char(now() AT TIME ZONE 'UTC', 'YYYYMMDDHH24')))
) AS actual_future_partitions,
sum(pg_total_relation_size(child.oid)) AS total_size_bytes,
pg_size_pretty(sum(pg_total_relation_size(child.oid))) AS total_size, pg_size_pretty(sum(pg_total_relation_size(child.oid))) AS total_size,
min(child.relname) AS oldest_partition, min(child.relname) AS oldest_partition,
max(child.relname) AS newest_partition, max(child.relname) AS newest_partition,
@@ -24,4 +31,4 @@ JOIN pg_class parent ON parent.relname = c.table_name
LEFT JOIN pg_inherits ON pg_inherits.inhparent = parent.oid LEFT JOIN pg_inherits ON pg_inherits.inhparent = parent.oid
LEFT JOIN pg_class child ON pg_inherits.inhrelid = child.oid LEFT JOIN pg_class child ON pg_inherits.inhrelid = child.oid
WHERE parent.relkind = 'p' -- Only partitioned tables WHERE parent.relkind = 'p' -- Only partitioned tables
GROUP BY parent.relname, c.table_name, c.period, c.keep_history, c.last_updated; GROUP BY parent.relname, c.table_name, c.period, c.keep_history, c.future_partitions, c.last_updated;

File diff suppressed because it is too large Load Diff