[comment]: # ({e26480a0-e26480a0})
# 3 Datenbank-Upgrade auf Primärschlüssel

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

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

Dieser Abschnitt enthält Anweisungen zum manuellen Upgrade von Tabellen in bestehenden Installationen auf Primärschlüssel.

Das Upgrade auf Primärschlüssel optimiert die Art und Weise, wie Daten indiziert und abgerufen werden, was Abfragen beschleunigen und Speicherplatz sparen kann.
Außerdem verbessert es die Datenverwaltung und Synchronisierung in Cluster-Umgebungen, unterstützt die Skalierung und stellt sicher, dass das System auch dann zuverlässig bleibt, wenn einige Server ausfallen.

::: noteimportant
Die auf dieser Seite bereitgestellten Anweisungen sind für fortgeschrittene Benutzer gedacht und müssen möglicherweise an Ihre spezifische Konfiguration angepasst werden.
Das Upgrade auf Primärschlüssel kann zeitaufwendig und ressourcenintensiv sein.
Stellen Sie sicher, dass ausreichend freier Festplattenspeicher verfügbar ist; abhängig von der Größe Ihrer Datenbank und den gespeicherten Daten kann der Prozess bis zum 2,5-Fachen des derzeit von Verlaufstabellen verwendeten Speicherplatzes benötigen.
:::

Primärschlüssel werden seit Zabbix 6.0 in neuen Installationen für alle Tabellen verwendet.

Es gibt kein automatisches Datenbank-Upgrade auf Primärschlüssel; bestehende Installationen können jedoch manuell **nach** dem Upgrade des Zabbix Server auf 6.0 oder neuer aktualisiert werden.

::: noteimportant
Seit Zabbix 7.0 werden beim Upgrade von Tabellen auf Primärschlüssel Tabellen auch für die Verwendung von double-precision-Datentypen aktualisiert.
<br><br>
Wenn Sie Zabbix 7.0 (oder neuer) verwenden, nutzen die Tabellen bereits double precision.
Die Anweisungen auf dieser Seite können jedoch weiterhin befolgt werden, um Tabellen auf Primärschlüssel zu aktualisieren, ohne Tabellen zu beeinflussen, die bereits double precision verwenden.
<br><br>
Wenn Sie Zabbix 6.4 (oder älter) verwenden, sollten Sie in Erwägung ziehen, Tabellen zuerst auf double precision zu aktualisieren.
Weitere Informationen finden Sie unter [Upgrading to numeric values of extended range](https://www.zabbix.com/documentation/7.0/en/manual/appendix/install/db_float_range) in der Zabbix-7.0-Dokumentation.
:::

Anweisungen sind verfügbar für:

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

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

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

So führen Sie das Datenbank-Upgrade durch:

1. Stoppen Sie den Zabbix Server.

Es wird dringend empfohlen, den Zabbix Server für die Dauer des Upgrades anzuhalten.
Falls jedoch unbedingt erforderlich, können Sie das Upgrade auch durchführen, während der Server läuft (nur für MySQL, MariaDB und PostgreSQL ohne TimescaleDB).

2. Erstellen Sie eine Sicherung Ihrer Datenbank.
3. Installieren Sie das neueste Paket zabbix-sql-scripts, das mit Ihrer Zabbix-Version kompatibel ist (z. B. für RHEL: `dnf install zabbix-sql-scripts`).
4. Führen Sie die Skripte für Ihre Datenbank aus.
5. Starten Sie den Zabbix Server.

::: notewarning
Führen Sie die Skripte nur für die Server-Datenbank aus.
Der Proxy profitiert nicht von diesem Upgrade.
:::

Wenn die Datenbank Partitionen verwendet, wenden Sie sich an den DB-Administrator oder den Zabbix-Support, um Hilfe zu erhalten.

CSV-Dateien können nach einem erfolgreichen Upgrade auf Primärschlüssel entfernt werden.

Optional kann das Zabbix Frontend in den [Wartungsmodus](/manual/web_interface/maintenance_mode) versetzt werden.

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

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

Export und Import müssen in tmux/screen durchgeführt werden, um sicherzustellen, dass die Sitzung nicht unterbrochen wird.

Siehe auch: [Wichtige Hinweise](#important-notes)

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

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

Diese Methode kann mit einem laufenden Zabbix Server verwendet werden, es wird jedoch empfohlen, den Server für die Dauer des Upgrades zu stoppen.
Die MySQL Shell (*mysqlsh*) muss [installiert](https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-install-linux-quick.html) sein und eine Verbindung zur DB herstellen können.

* Melden Sie sich in der MySQL-Konsole als root an (empfohlen) oder als beliebiger Benutzer mit FILE-Rechten.

* Starten Sie MySQL mit aktivierter Variable [local_infile](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_local_infile).

* Benennen Sie alte Tabellen um und erstellen Sie neue Tabellen, indem Sie `history_upgrade_prepare.sql` ausführen.

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

* Exportieren und importieren Sie Daten.

Verbinden Sie sich über mysqlsh. Bei Verwendung einer Socket-Verbindung kann es erforderlich sein, den Pfad anzugeben.

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

Wechseln Sie mit folgendem Befehl in den JavaScript-Modus:

```sqlmysql
\js
```

Führen Sie dann den folgenden Code aus (CSVPATH kann bei Bedarf geändert werden):

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

Wenn die Meldung "JavaScript is not supported" angezeigt wird, unterstützt Ihre MySQL Shell-Installation kein JS.
Installieren Sie in diesem Fall das offizielle [MySQL Shell-Paket](https://dev.mysql.com/downloads/shell/) von Oracle (oder erstellen Sie es aus dem Quellcode), damit der JavaScript-Modus aktiviert ist.

* Befolgen Sie die [Anweisungen nach der Migration](#postmigration), um die alten Tabellen zu löschen.

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

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

Diese Upgrade-Methode dauert länger und sollte nur verwendet werden, wenn ein Upgrade mit *mysqlsh* nicht möglich ist.

##### Tabellen-Upgrade

* Melden Sie sich in der MySQL-Konsole als root an (empfohlen) oder als beliebiger Benutzer mit FILE-Rechten.

* Wenn Sie die Migration mit einem laufenden Zabbix-Server durchführen, starten Sie MySQL mit aktivierter Variable [local_infile](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_local_infile).

* Benennen Sie alte Tabellen um und erstellen Sie neue Tabellen, indem Sie `history_upgrade_prepare.sql` ausführen:

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

##### Migration mit gestopptem Server

`max_execution_time` (in MySQL) oder `max_statement_time` (in MariaDB) muss vor der Migration der Daten deaktiviert werden, um ein Timeout während der Migration zu vermeiden.

Für MySQL:

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

Für 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;
```

Befolgen Sie die [Anweisungen nach der Migration](#postmigration), um die alten Tabellen zu löschen.

##### Migration mit laufendem Server

Prüfen Sie, für welche Pfade Import/Export aktiviert ist:

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

Wenn der Wert von *secure_file_priv* ein Pfad zu einem Verzeichnis ist, wird der Export/Import für Dateien in diesem Verzeichnis durchgeführt.
Bearbeiten Sie in diesem Fall die Pfade zu den Dateien in den Abfragen entsprechend oder setzen Sie den Wert von *secure_file_priv* für die Dauer des Upgrades auf eine leere Zeichenfolge.

Wenn der Wert von *secure_file_priv* leer ist, kann der Export/Import von jedem Speicherort aus durchgeführt werden.

Wenn der Wert von *secure_file_priv* NULL ist, setzen Sie ihn auf den Pfad, der die exportierten Tabellendaten enthält (im obigen Beispiel '/var/lib/mysql-files/').

Weitere Informationen finden Sie in der [MySQL-Dokumentation](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_secure_file_priv) oder in der [MariaDB-Dokumentation](https://mariadb.com/docs/server/ha-and-performance/optimization-and-tuning/system-variables/server-system-variables#secure_file_priv).

`max_execution_time` (in MySQL) oder `max_statement_time` (in MariaDB) muss vor dem Export der Daten deaktiviert werden, um ein Timeout während des Exports zu vermeiden.

Für MySQL:

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

Für 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';
```

Befolgen Sie die [Anweisungen nach der Migration](#postmigration), um die alten Tabellen zu löschen.

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

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

Export und Import müssen in tmux/screen durchgeführt werden, um sicherzustellen, dass die Sitzung nicht getrennt wird.
Bei Installationen mit TimescaleDB überspringen Sie diesen Abschnitt und fahren Sie mit [PostgreSQL + TimescaleDB](#postgresql-timescaledb) fort.

Siehe auch: [Wichtige Hinweise](#important-notes)

#### Tabellenupgrade

* Benennen Sie Tabellen mit `history_upgrade_prepare.sql` um:

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

#### Migration mit gestopptem Server

* Exportieren Sie den aktuellen Verlauf, importieren Sie ihn in die temporäre Tabelle und fügen Sie dann die Daten unter Ignorieren von Duplikaten in die neuen Tabellen ein:

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

Siehe Tipps zur Verbesserung der INSERT-Performance: [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).

* Folgen Sie den [Anweisungen nach der Migration](#postmigration), um die alten Tabellen zu löschen.

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

[comment]: # ({e951ec07-7e590ff3})
#### Migration mit laufendem Server

* Exportieren Sie den aktuellen Verlauf, importieren Sie ihn in die temporäre Tabelle und fügen Sie die Daten dann unter Ignorieren von Duplikaten in die neuen Tabellen ein:

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

* Folgen Sie den [Anweisungen nach der Migration](#postmigration), um die alten Tabellen zu löschen.

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

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

Export und Import müssen in tmux/screen durchgeführt werden, um sicherzustellen, dass die Sitzung nicht getrennt wird.
Der Zabbix Server sollte während des Upgrades heruntergefahren sein.

Siehe auch: [Wichtige Hinweise](#important-notes)

* Benennen Sie Tabellen mit `history_upgrade_prepare.sql` um.
  * Wenn die Komprimierung aktiviert ist (bei der Standardinstallation), führen Sie das Skript aus `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression` aus:
    ```bash
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
    ```
  * Wenn die Komprimierung deaktiviert ist, führen Sie das Skript aus `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression` aus:
    ```bash
    cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
    ```

* Führen Sie die TimescaleDB-Hypertable-Migrationsskripte basierend auf den Komprimierungseinstellungen aus:
  * Wenn die Komprimierung aktiviert ist (bei der Standardinstallation), führen Sie die Skripte aus `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression` aus:
    ```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
    ```
  * Wenn die Komprimierung deaktiviert ist, führen Sie die Skripte aus `/usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression` aus:
    ```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
    ```

Siehe auch: [Tipps](https://www.tigerdata.com/blog/13-tips-to-improve-postgresql-insert-performance) zur Verbesserung der INSERT-Performance.

* Befolgen Sie die [Anweisungen nach der Migration](#postmigration), um die alten Tabellen zu löschen.

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

[comment]: # ({e73536ae-b041e427})
### Nach der Migration

Führen Sie für alle Datenbanken nach Abschluss der Migration Folgendes durch:

* Überprüfen Sie, dass alles wie erwartet funktioniert.

* Löschen Sie die alten Tabellen:

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

* Löschen Sie bei TimescaleDB zusätzlich die folgende alte Tabelle:

```sql
DROP TABLE trends_old;
```

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

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

-   [Vorbereiten der Auditlog-Tabelle für die Partitionierung](/manual/appendix/install/auditlog_primary_keys)

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