[comment]: # ({e26480a0-e26480a0})
# 3 Aggiornamento del database alle chiavi primarie

[comment]: # ({/e26480a0-e26480a0})

[comment]: # ({c4558d36-53564572})
### Panoramica

Questa sezione fornisce istruzioni per aggiornare manualmente le tabelle nelle installazioni esistenti alle chiavi primarie.

L'aggiornamento alle chiavi primarie ottimizza il modo in cui i dati vengono indicizzati e consultati, il che può velocizzare le query e risparmiare spazio.
Migliora inoltre la gestione e la sincronizzazione dei dati nelle configurazioni cluster, facilitando la scalabilità e garantendo che il sistema rimanga affidabile anche in caso di guasto di alcuni server.

::: noteimportant
Le istruzioni fornite in questa pagina sono pensate per utenti avanzati e potrebbero dover essere adattate alla configurazione specifica in uso.
L'aggiornamento alle chiavi primarie può richiedere molto tempo e molte risorse.
Assicurarsi che sia disponibile spazio libero su disco sufficiente; a seconda delle dimensioni del database e dei dati memorizzati, il processo potrebbe richiedere fino a 2,5 volte lo spazio attualmente utilizzato dalle tabelle dello storico.
:::

Le chiavi primarie vengono utilizzate per tutte le tabelle nelle nuove installazioni a partire da Zabbix 6.0.

Non esiste un aggiornamento automatico del database alle chiavi primarie; tuttavia, le installazioni esistenti possono essere aggiornate manualmente **dopo** aver aggiornato Zabbix server alla versione 6.0 o successiva.

::: noteimportant
A partire da Zabbix 7.0, l'aggiornamento delle tabelle alle chiavi primarie aggiorna anche le tabelle affinché utilizzino tipi di dati double precision.
<br><br>
Se si utilizza Zabbix 7.0 (o successivo), le tabelle utilizzano già double precision.
Tuttavia, è comunque possibile seguire le istruzioni in questa pagina per aggiornare le tabelle alle chiavi primarie senza influire sulle tabelle che utilizzano già double precision.
<br><br>
Se si utilizza Zabbix 6.4 (o precedente), valutare prima l'aggiornamento delle tabelle a double precision.
Per ulteriori informazioni, vedere [Upgrading to numeric values of extended range](https://www.zabbix.com/documentation/7.0/en/manual/appendix/install/db_float_range) nella documentazione di Zabbix 7.0.
:::

Sono disponibili istruzioni per:

* [MySQL](#mysql)
* [PostgreSQL](#postgresql)
* [TimescaleDB](#postgresql-timescaledb)

[comment]: # ({/c4558d36-53564572})

[comment]: # ({5c5adaf8-980f7329})
### Note importanti

Per eseguire l'aggiornamento del database:

1. Arrestare Zabbix server.

Si consiglia vivamente di arrestare Zabbix server per la durata dell'aggiornamento.
Tuttavia, se strettamente necessario, è possibile eseguire l'aggiornamento mentre il server è in esecuzione (solo per MySQL, MariaDB e PostgreSQL senza TimescaleDB).

2. Eseguire un backup del database.
3. Installare il pacchetto zabbix-sql-scripts più recente compatibile con la propria versione di Zabbix (ad esempio, per RHEL: `dnf install zabbix-sql-scripts`).
4. Eseguire gli script per il proprio database.
5. Avviare Zabbix server.

::: notewarning
Eseguire gli script solo per il database del server.
Il proxy non trarrà beneficio da questo aggiornamento.
:::

Se il database utilizza partizioni, contattare l'amministratore DB o il Supporto Zabbix per assistenza.

I file CSV possono essere rimossi dopo un aggiornamento riuscito alle chiavi primarie.

Facoltativamente, Zabbix frontend può essere impostato in [modalità di manutenzione](/manual/web_interface/maintenance_mode).

[comment]: # ({/5c5adaf8-980f7329})

[comment]: # ({4f99bcf1-1551eb55})
### MySQL

L'esportazione e l'importazione devono essere eseguite in tmux/screen per garantire che la sessione non venga interrotta.

Vedi anche: [Note importanti](#important-notes)

[comment]: # ({/4f99bcf1-1551eb55})

[comment]: # ({ddfd920a-dc89d749})
#### MySQL 8.0+ con mysqlsh

Questo metodo può essere usato con un server Zabbix in esecuzione, ma si consiglia di arrestare il server per la durata dell'aggiornamento.
MySQL Shell (*mysqlsh*) deve essere [installato](https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-install-linux-quick.html) e in grado di connettersi al DB.

* Accedere alla console MySQL come root (consigliato) oppure come qualsiasi utente con privilegi FILE.

* Avviare MySQL con la variabile [local_infile](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_local_infile) abilitata.

* Rinominare le vecchie tabelle e creare le nuove eseguendo `history_upgrade_prepare.sql`.

```bash
mysql -uzabbix -p<password> zabbix < /usr/share/zabbix/sql-scripts/mysql/option-patches/history_upgrade_prepare.sql
```

* Esportare e importare i dati.

Connettersi tramite mysqlsh. Se si utilizza una connessione socket, potrebbe essere necessario specificare il percorso.

```bash
sudo mysqlsh -uroot -S /run/mysqld/mysqld.sock --no-password -Dzabbix
```

Passare alla modalità JavaScript usando:

```sqlmysql
\js
```

Quindi eseguire il codice seguente (CSVPATH può essere modificato secondo necessità):

```javascript
CSVPATH="/var/lib/mysql-files";

util.exportTable("history_old", CSVPATH + "/history.csv", { dialect: "csv" });
util.importTable(CSVPATH + "/history.csv", {"dialect": "csv", "table": "history" });

util.exportTable("history_uint_old", CSVPATH + "/history_uint.csv", { dialect: "csv" });
util.importTable(CSVPATH + "/history_uint.csv", {"dialect": "csv", "table": "history_uint" });

util.exportTable("history_str_old", CSVPATH + "/history_str.csv", { dialect: "csv" });
util.importTable(CSVPATH + "/history_str.csv", {"dialect": "csv", "table": "history_str" });

util.exportTable("history_log_old", CSVPATH + "/history_log.csv", { dialect: "csv" });
util.importTable(CSVPATH + "/history_log.csv", {"dialect": "csv", "table": "history_log" });

util.exportTable("history_text_old", CSVPATH + "/history_text.csv", { dialect: "csv" });
util.importTable(CSVPATH + "/history_text.csv", {"dialect": "csv", "table": "history_text" });
```

Se viene visualizzato il messaggio "JavaScript is not supported", l'installazione di MySQL Shell non include il supporto JS.
In tal caso, installare il pacchetto ufficiale [MySQL Shell package](https://dev.mysql.com/downloads/shell/) di Oracle (oppure compilarlo dai sorgenti) in modo che la modalità JavaScript sia abilitata.

* Seguire le [istruzioni post-migrazione](#postmigration) per eliminare le vecchie tabelle.

[comment]: # ({/ddfd920a-dc89d749})

[comment]: # ({13c44439-b132f69b})
#### MariaDB/MySQL 8.0+ senza mysqlsh

Questo metodo di aggiornamento richiede più tempo e deve essere usato solo se un aggiornamento con *mysqlsh* non è possibile.

##### Aggiornamento delle tabelle

* Accedi alla console MySQL come root (consigliato) oppure come qualsiasi utente con privilegi FILE.

* Se esegui la migrazione con un server Zabbix in esecuzione, avvia MySQL con la variabile [local_infile](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_local_infile) abilitata.

* Rinomina le vecchie tabelle e crea le nuove eseguendo `history_upgrade_prepare.sql`:

```bash
mysql -uzabbix -p<password> zabbix < /usr/share/zabbix/sql-scripts/mysql/option-patches/history_upgrade_prepare.sql
```

##### Migrazione con server arrestato

`max_execution_time` (in MySQL) o `max_statement_time` (in MariaDB) devono essere disabilitati prima della migrazione dei dati per evitare timeout durante la migrazione.

Per MySQL:

```sql
SET @@max_execution_time=0;
```

Per MariaDB:

```sql
SET @@max_statement_time=0;
```

```sql
INSERT IGNORE INTO history SELECT * FROM history_old;
INSERT IGNORE INTO history_uint SELECT * FROM history_uint_old;
INSERT IGNORE INTO history_str SELECT * FROM history_str_old;
INSERT IGNORE INTO history_log SELECT * FROM history_log_old;
INSERT IGNORE INTO history_text SELECT * FROM history_text_old;
```

Segui le [istruzioni post-migrazione](#postmigration) per eliminare le vecchie tabelle.

##### Migrazione con server in esecuzione

Verifica per quali percorsi l'importazione/esportazione è abilitata:

```sql
mysql> SELECT @@secure_file_priv;
+-----------------------+
| @@secure_file_priv    |
+-----------------------+
| /var/lib/mysql-files/ |
+-----------------------+
```

Se il valore di *secure_file_priv* è un percorso a una directory, l'esportazione/importazione verrà eseguita per i file in quella directory.
In questo caso, modifica di conseguenza i percorsi dei file nelle query oppure imposta il valore di *secure_file_priv* su una stringa vuota per il tempo dell'aggiornamento.

Se il valore di *secure_file_priv* è vuoto, l'esportazione/importazione può essere eseguita da qualsiasi posizione.

Se il valore di *secure_file_priv* è NULL, impostalo sul percorso che contiene i dati esportati della tabella ('/var/lib/mysql-files/' nell'esempio sopra).

Per ulteriori informazioni, consulta la [documentazione MySQL](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_secure_file_priv) o la [documentazione MariaDB](https://mariadb.com/docs/server/ha-and-performance/optimization-and-tuning/system-variables/server-system-variables#secure_file_priv).

`max_execution_time` (in MySQL) o `max_statement_time` (in MariaDB) devono essere disabilitati prima dell'esportazione dei dati per evitare timeout durante l'esportazione.

Per MySQL:

```sql
SET @@max_execution_time=0;
```

Per MariaDB:

```sql
SET @@max_statement_time=0;
```

```sql
SELECT * INTO OUTFILE '/var/lib/mysql-files/history.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_old;
LOAD DATA INFILE '/var/lib/mysql-files/history.csv' IGNORE INTO TABLE history FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';

SELECT * INTO OUTFILE '/var/lib/mysql-files/history_uint.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_uint_old;
LOAD DATA INFILE '/var/lib/mysql-files/history_uint.csv' IGNORE INTO TABLE history_uint FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';

SELECT * INTO OUTFILE '/var/lib/mysql-files/history_str.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_str_old;
LOAD DATA INFILE '/var/lib/mysql-files/history_str.csv' IGNORE INTO TABLE history_str FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';

SELECT * INTO OUTFILE '/var/lib/mysql-files/history_log.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_log_old;
LOAD DATA INFILE '/var/lib/mysql-files/history_log.csv' IGNORE INTO TABLE history_log FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';

SELECT * INTO OUTFILE '/var/lib/mysql-files/history_text.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_text_old;
LOAD DATA INFILE '/var/lib/mysql-files/history_text.csv' IGNORE INTO TABLE history_text FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';
```

Segui le [istruzioni post-migrazione](#postmigration) per eliminare le vecchie tabelle.

[comment]: # ({/13c44439-b132f69b})

[comment]: # ({8e581875-1139207b})
### PostgreSQL

L'esportazione e l'importazione devono essere eseguite in tmux/screen per garantire che la sessione non venga interrotta.
Per le installazioni con TimescaleDB, saltare questa sezione e procedere a [PostgreSQL + TimescaleDB](#postgresql-timescaledb).

Vedi anche: [Note importanti](#important-notes)

#### Aggiornamento delle tabelle

* Rinominare le tabelle usando `history_upgrade_prepare.sql`:

```bash
sudo -u zabbix psql zabbix < /usr/share/zabbix/sql-scripts/postgresql/option-patches/history_upgrade_prepare.sql
```

#### Migrazione con server arrestato

* Esportare la cronologia corrente, importarla nella tabella temporanea, quindi inserire i dati nelle nuove tabelle ignorando i duplicati:

```sql
INSERT INTO history SELECT * FROM history_old ON CONFLICT (itemid,clock,ns) DO NOTHING;

INSERT INTO history_uint SELECT * FROM history_uint_old ON CONFLICT (itemid,clock,ns) DO NOTHING;

INSERT INTO history_str SELECT * FROM history_str_old ON CONFLICT (itemid,clock,ns) DO NOTHING;

INSERT INTO history_log SELECT * FROM history_log_old ON CONFLICT (itemid,clock,ns) DO NOTHING;

INSERT INTO history_text SELECT * FROM history_text_old ON CONFLICT (itemid,clock,ns) DO NOTHING;
```

Vedi i suggerimenti per migliorare le prestazioni di INSERT: [PostgreSQL: Bulk Loading Huge Amounts of Data](https://www.cybertec-postgresql.com/en/postgresql-bulk-loading-huge-amounts-of-data), [Checkpoint Distance and Amount of WAL](https://www.cybertec-postgresql.com/en/checkpoint-distance-and-amount-of-wal).

* Seguire le [istruzioni post-migrazione](#postmigration) per eliminare le vecchie tabelle.

[comment]: # ({/8e581875-1139207b})

[comment]: # ({e951ec07-7e590ff3})
#### Migrazione con server in esecuzione

* Esporta la cronologia corrente, importala nella tabella temporanea, quindi inserisci i dati nelle nuove tabelle ignorando i duplicati:

```sql
\copy history_old TO '/tmp/history.csv' DELIMITER ',' CSV
CREATE TEMP TABLE temp_history (
    itemid                   bigint                                    NOT NULL,
    clock                    integer         DEFAULT '0'               NOT NULL,
    value                    DOUBLE PRECISION DEFAULT '0.0000'          NOT NULL,
    ns                       integer         DEFAULT '0'               NOT NULL
);
\copy temp_history FROM '/tmp/history.csv' DELIMITER ',' CSV
INSERT INTO history SELECT * FROM temp_history ON CONFLICT (itemid,clock,ns) DO NOTHING;

\copy history_uint_old TO '/tmp/history_uint.csv' DELIMITER ',' CSV
CREATE TEMP TABLE temp_history_uint (
    itemid                   bigint                                    NOT NULL,
    clock                    integer         DEFAULT '0'               NOT NULL,
    value                    numeric(20)     DEFAULT '0'               NOT NULL,
    ns                       integer         DEFAULT '0'               NOT NULL
);
\copy temp_history_uint FROM '/tmp/history_uint.csv' DELIMITER ',' CSV
INSERT INTO history_uint SELECT * FROM temp_history_uint ON CONFLICT (itemid,clock,ns) DO NOTHING;

\copy history_str_old TO '/tmp/history_str.csv' DELIMITER ',' CSV
CREATE TEMP TABLE temp_history_str (
    itemid                   bigint                                    NOT NULL,
    clock                    integer         DEFAULT '0'               NOT NULL,
    value                    varchar(255)    DEFAULT ''                NOT NULL,
    ns                       integer         DEFAULT '0'               NOT NULL
);
\copy temp_history_str FROM '/tmp/history_str.csv' DELIMITER ',' CSV
INSERT INTO history_str (itemid,clock,value,ns) SELECT * FROM temp_history_str ON CONFLICT (itemid,clock,ns) DO NOTHING;

\copy history_log_old TO '/tmp/history_log.csv' DELIMITER ',' CSV
CREATE TEMP TABLE temp_history_log (
    itemid                   bigint                                    NOT NULL,
    clock                    integer         DEFAULT '0'               NOT NULL,
    timestamp                integer         DEFAULT '0'               NOT NULL,
    source                   varchar(64)     DEFAULT ''                NOT NULL,
    severity                 integer         DEFAULT '0'               NOT NULL,
    value                    text            DEFAULT ''                NOT NULL,
    logeventid               integer         DEFAULT '0'               NOT NULL,
    ns                       integer         DEFAULT '0'               NOT NULL
);
\copy temp_history_log FROM '/tmp/history_log.csv' DELIMITER ',' CSV
INSERT INTO history_log SELECT * FROM temp_history_log ON CONFLICT (itemid,clock,ns) DO NOTHING;

\copy history_text_old TO '/tmp/history_text.csv' DELIMITER ',' CSV
CREATE TEMP TABLE temp_history_text (
    itemid                   bigint                                    NOT NULL,
    clock                    integer         DEFAULT '0'               NOT NULL,
    value                    text            DEFAULT ''                NOT NULL,
    ns                       integer         DEFAULT '0'               NOT NULL
);
\copy temp_history_text FROM '/tmp/history_text.csv' DELIMITER ',' CSV
INSERT INTO history_text SELECT * FROM temp_history_text ON CONFLICT (itemid,clock,ns) DO NOTHING;
```

* Segui le [istruzioni post-migrazione](#postmigration) per eliminare le vecchie tabelle.

[comment]: # ({/e951ec07-7e590ff3})

[comment]: # ({4e372941-589d2f09})
### PostgreSQL + TimescaleDB

L'esportazione e l'importazione devono essere eseguite in tmux/screen per garantire che la sessione non venga interrotta.
Il server Zabbix deve essere arrestato durante l'aggiornamento.

Vedi anche: [Note importanti](#important-notes)

* Rinominare le tabelle usando `history_upgrade_prepare.sql`.
  * Se la compressione è abilitata (nell'installazione predefinita), eseguire lo script da `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression`:
    ```bash
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
    ```
  * Se la compressione è disabilitata, eseguire lo script da `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression`:
    ```bash
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
    ```

* Eseguire gli script di migrazione delle hypertable di TimescaleDB in base alle impostazioni di compressione:
  * Se la compressione è abilitata (nell'installazione predefinita), eseguire gli script da `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression`:
    ```bash
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_uint.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_log.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_str.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_text.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/trends_upgrade.sql | sudo -u zabbix psql zabbix
    ```
  * Se la compressione è disabilitata, eseguire gli script da `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression`:
    ```bash
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_uint.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_log.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_str.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_text.sql | sudo -u zabbix psql zabbix
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/trends_upgrade.sql | sudo -u zabbix psql zabbix
    ```

Vedi anche: [Suggerimenti](https://www.tigerdata.com/blog/13-tips-to-improve-postgresql-insert-performance) per migliorare le prestazioni di INSERT.

* Seguire le [istruzioni post-migrazione](#postmigration) per eliminare le vecchie tabelle.

[comment]: # ({/4e372941-589d2f09})

[comment]: # ({e73536ae-b041e427})
### Post-migrazione

Per tutti i database, una volta completata la migrazione, procedere come segue:

* Verificare che tutto funzioni come previsto.

* Eliminare le vecchie tabelle:

```sql
DROP TABLE history_old;
DROP TABLE history_uint_old;
DROP TABLE history_str_old;
DROP TABLE history_log_old;
DROP TABLE history_text_old;
```

* Per TimescaleDB, eliminare anche la seguente vecchia tabella:

```sql
DROP TABLE trends_old;
```

[comment]: # ({/e73536ae-b041e427})

[comment]: # ({16ed11f0-8ee7d9aa})
#### Vedi anche

-   [Preparazione della tabella auditlog per il partizionamento](/manual/appendix/install/auditlog_primary_keys)

[comment]: # ({/16ed11f0-8ee7d9aa})
