[comment]: # ({e26480a0-e26480a0})
# 3 Mise à niveau de la base de données vers des clés primaires

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

[comment]: # ({c4558d36-53564572})
### Aperçu

Cette section fournit des instructions pour mettre à niveau manuellement les tables des installations existantes vers des clés primaires.

La mise à niveau vers des clés primaires optimise la façon dont les données sont indexées et consultées, ce qui peut accélérer les requêtes et économiser de l’espace.
Elle améliore également la gestion et la synchronisation des données dans les configurations en cluster, ce qui facilite la montée en charge et garantit que le système reste fiable même en cas de défaillance de certains serveurs.

::: noteimportant
Les instructions fournies sur cette page sont destinées aux utilisateurs avancés et peuvent nécessiter des ajustements en fonction de votre configuration spécifique.
La mise à niveau vers des clés primaires peut prendre du temps et consommer beaucoup de ressources.
Assurez-vous qu’un espace disque libre suffisant est disponible ; selon la taille de votre base de données et les données stockées, le processus peut nécessiter jusqu’à 2,5 fois l’espace actuellement utilisé par les tables d’historique.
:::

Les clés primaires sont utilisées pour toutes les tables dans les nouvelles installations depuis Zabbix 6.0.

Il n’existe pas de mise à niveau automatique de la base de données vers des clés primaires ; toutefois, les installations existantes peuvent être mises à niveau manuellement **après** la mise à niveau du serveur Zabbix vers la version 6.0 ou ultérieure.

::: noteimportant
Depuis Zabbix 7.0, la mise à niveau des tables vers des clés primaires met également à niveau les tables afin qu’elles utilisent des types de données en double précision.
<br><br>
Si vous utilisez Zabbix 7.0 (ou une version ultérieure), les tables utilisent déjà la double précision.
Cependant, les instructions de cette page peuvent toujours être suivies pour mettre à niveau les tables vers des clés primaires sans affecter les tables qui utilisent déjà la double précision.
<br><br>
Si vous utilisez Zabbix 6.4 (ou une version antérieure), envisagez d’abord de mettre à niveau les tables vers la double précision.
Pour plus d’informations, consultez [Mise à niveau vers des valeurs numériques à plage étendue](https://www.zabbix.com/documentation/7.0/en/manual/appendix/install/db_float_range) dans la documentation de Zabbix 7.0.
:::

Des instructions sont disponibles pour :

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

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

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

Pour effectuer la mise à niveau de la base de données :

1. Arrêtez le serveur Zabbix.

Il est fortement recommandé d’arrêter le serveur Zabbix pendant la durée de la mise à niveau.
Cependant, si cela est absolument nécessaire, vous pouvez effectuer la mise à niveau pendant que le serveur est en cours d’exécution (uniquement pour MySQL, MariaDB et PostgreSQL sans TimescaleDB).

2. Sauvegardez votre base de données.
3. Installez le dernier paquet zabbix-sql-scripts compatible avec votre version de Zabbix (par exemple, pour RHEL : `dnf install zabbix-sql-scripts`).
4. Exécutez les scripts pour votre base de données.
5. Démarrez le serveur Zabbix.

::: notewarning
Exécutez les scripts uniquement pour la base de données du serveur.
Le proxy ne bénéficiera pas de cette mise à niveau.
:::

Si la base de données utilise des partitions, contactez l’administrateur de la base de données ou le support Zabbix pour obtenir de l’aide.

Les fichiers CSV peuvent être supprimés après une mise à niveau réussie vers des clés primaires.

En option, le frontend Zabbix peut être basculé en [mode maintenance](/manual/web_interface/maintenance_mode).

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

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

L'exportation et l'importation doivent être effectuées dans tmux/screen pour s'assurer que la session n'est pas abandonnée.

Voir également : [Notes importantes](#important-notes)

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

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

Cette méthode peut être utilisée avec un serveur Zabbix en cours d'exécution, mais il est recommandé d'arrêter le serveur pendant la durée de la mise à niveau.
MySQL Shell (*mysqlsh*) doit être [installé](https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-install-linux-quick.html) et pouvoir se connecter à la base de données.

* Connectez-vous à la console MySQL en tant que root (recommandé) ou en tant que tout utilisateur disposant des privilèges FILE.

* Démarrez MySQL avec la variable [local_infile](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_local_infile) activée.

* Renommez les anciennes tables et créez les nouvelles tables en exécutant `history_upgrade_prepare.sql`.

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

* Exportez et importez les données.

Connectez-vous via mysqlsh. Si vous utilisez une connexion par socket, il peut être nécessaire de spécifier le chemin.

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

Passez en mode JavaScript à l'aide de :

```sqlmysql
\js
```

Exécutez ensuite le code ci-dessous (CSVPATH peut être modifié selon les besoins) :

```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" });
```

Si vous recevez le message "JavaScript is not supported", votre installation de MySQL Shell ne prend pas en charge JS.
Dans ce cas, installez le [package officiel MySQL Shell](https://dev.mysql.com/downloads/shell/) d'Oracle (ou compilez-le à partir des sources) afin que le mode JavaScript soit activé.

* Suivez les [instructions post-migration](#postmigration) pour supprimer les anciennes tables.

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

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

Cette méthode de mise à niveau prend plus de temps et ne doit être utilisée que si une mise à niveau avec *mysqlsh* n'est pas possible.

##### Mise à niveau des tables

* Connectez-vous à la console MySQL en tant que root (recommandé) ou en tant que tout utilisateur disposant des privilèges FILE.

* Si vous effectuez la migration avec un serveur Zabbix en cours d'exécution, démarrez MySQL avec la variable [local_infile](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_local_infile) activée.

* Renommez les anciennes tables et créez les nouvelles tables en exécutant `history_upgrade_prepare.sql` :

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

##### Migration avec serveur arrêté

`max_execution_time` (dans MySQL) ou `max_statement_time` (dans MariaDB) doit être désactivé avant la migration des données afin d'éviter un dépassement de délai pendant la migration.

Pour MySQL :

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

Pour 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;
```

Suivez les [instructions post-migration](#postmigration) pour supprimer les anciennes tables.

##### Migration avec serveur en cours d'exécution

Vérifiez pour quels chemins l'import/export est activé :

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

Si la valeur de *secure_file_priv* est un chemin vers un répertoire, l'export/import sera effectué pour les fichiers de ce répertoire.
Dans ce cas, modifiez les chemins vers les fichiers dans les requêtes en conséquence ou définissez la valeur *secure_file_priv* sur une chaîne vide pendant la mise à niveau.

Si la valeur de *secure_file_priv* est vide, l'export/import peut être effectué depuis n'importe quel emplacement.

Si la valeur de *secure_file_priv* est NULL, définissez-la sur le chemin qui contient les données exportées des tables ('/var/lib/mysql-files/' dans l'exemple ci-dessus).

Pour plus d'informations, consultez la [documentation MySQL](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_secure_file_priv) ou la [documentation MariaDB](https://mariadb.com/docs/server/ha-and-performance/optimization-and-tuning/system-variables/server-system-variables#secure_file_priv).

`max_execution_time` (dans MySQL) ou `max_statement_time` (dans MariaDB) doit être désactivé avant l'exportation des données afin d'éviter un dépassement de délai pendant l'exportation.

Pour MySQL :

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

Pour 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';
```

Suivez les [instructions post-migration](#postmigration) pour supprimer les anciennes tables.

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

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

L'exportation et l'importation doivent être effectuées dans tmux/screen afin de garantir que la session ne soit pas interrompue.
Pour les installations avec TimescaleDB, ignorez cette section et passez à [PostgreSQL + TimescaleDB](#postgresql-timescaledb).

Voir aussi : [Notes importantes](#important-notes)

#### Mise à niveau des tables

* Renommez les tables à l'aide de `history_upgrade_prepare.sql` :

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

#### Migration avec serveur arrêté

* Exportez l'historique actuel, importez-le dans la table temporaire, puis insérez les données dans les nouvelles tables tout en ignorant les doublons :

```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;
```

Voir les conseils pour améliorer les performances de 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).

* Suivez les [instructions post-migration](#postmigration) pour supprimer les anciennes tables.

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

[comment]: # ({e951ec07-7e590ff3})
#### Migration avec serveur en cours d'exécution

* Exportez l'historique actuel, importez-le dans la table temporaire, puis insérez les données dans les nouvelles tables en ignorant les doublons :

```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;
```

* Suivez les [instructions post-migration](#postmigration) pour supprimer les anciennes tables.

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

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

L'exportation et l'importation doivent être effectués dans tmux/screen afin de garantir que la session ne soit pas interrompue.
Le serveur Zabbix doit être arrêté pendant la mise à niveau.

Voir aussi: [Notes importantes](#important-notes)

* Renommez les tables à l'aide de `history_upgrade_prepare.sql`.
  * Si la compression est activée (dans l'installation par défaut), exécutez le script depuis `/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
    ```
  * Si la compression est désactivée, exécutez le script depuis `/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
    ```

* Exécutez les scripts de migration des hypertables TimescaleDB en fonction des paramètres de compression:
  * Si la compression est activée (dans l'installation par défaut), exécutez les scripts depuis `/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
    ```
  * Si la compression est désactivée, exécutez les scripts depuis `/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
    ```

Voir aussi: [Conseils](https://www.tigerdata.com/blog/13-tips-to-improve-postgresql-insert-performance) pour améliorer les performances d'INSERT.

* Suivez les [instructions post-migration](#postmigration) pour supprimer les anciennes tables.

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

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

Pour toutes les bases de données, une fois la migration terminée, procédez comme suit :

* Vérifiez que tout fonctionne comme prévu.

* Supprimez les anciennes tables :

```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;
```

* Pour TimescaleDB, supprimez également l’ancienne table suivante :

```sql
DROP TABLE trends_old;
```

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

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

-   [Préparation de la table auditlog pour le partitionnement](/manual/appendix/install/auditlog_primary_keys)

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